123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440 |
- // SPDX-License-Identifier: GPL-2.0+
- /*
- * FSL PAMU driver
- *
- * Copyright 2012-2016 Freescale Semiconductor, Inc.
- */
- #include <common.h>
- #include <linux/log2.h>
- #include <malloc.h>
- #include <asm/fsl_pamu.h>
- struct paace *ppaact;
- struct paace *sec;
- unsigned long fspi;
- static inline int __ilog2_roundup_64(uint64_t val)
- {
- if ((val & (val - 1)) == 0)
- return __ilog2_u64(val);
- else
- return __ilog2_u64(val) + 1;
- }
- static inline int count_lsb_zeroes(unsigned long val)
- {
- return ffs(val) - 1;
- }
- static unsigned int map_addrspace_size_to_wse(uint64_t addrspace_size)
- {
- /* window size is 2^(WSE+1) bytes */
- return count_lsb_zeroes(addrspace_size >> PAMU_PAGE_SHIFT) +
- PAMU_PAGE_SHIFT - 1;
- }
- static unsigned int map_subwindow_cnt_to_wce(uint32_t subwindow_cnt)
- {
- /* window count is 2^(WCE+1) bytes */
- return count_lsb_zeroes(subwindow_cnt) - 1;
- }
- static void pamu_setup_default_xfer_to_host_ppaace(struct paace *ppaace)
- {
- set_bf(ppaace->addr_bitfields, PAACE_AF_PT, PAACE_PT_PRIMARY);
- set_bf(ppaace->domain_attr.to_host.coherency_required, PAACE_DA_HOST_CR,
- PAACE_M_COHERENCE_REQ);
- }
- static void pamu_setup_default_xfer_to_host_spaace(struct paace *spaace)
- {
- set_bf(spaace->addr_bitfields, PAACE_AF_PT, PAACE_PT_SECONDARY);
- set_bf(spaace->domain_attr.to_host.coherency_required, PAACE_DA_HOST_CR,
- PAACE_M_COHERENCE_REQ);
- }
- /** Sets up PPAACE entry for specified liodn
- *
- * @param[in] liodn Logical IO device number
- * @param[in] win_addr starting address of DSA window
- * @param[in] win-size size of DSA window
- * @param[in] omi Operation mapping index -- if ~omi == 0 then omi
- not defined
- * @param[in] stashid cache stash id for associated cpu -- if ~stashid == 0
- then stashid not defined
- * @param[in] snoopid snoop id for hardware coherency -- if ~snoopid == 0
- then snoopid not defined
- * @param[in] subwin_cnt number of sub-windows
- *
- * @return Returns 0 upon success else error code < 0 returned
- */
- static int pamu_config_ppaace(uint32_t liodn, uint64_t win_addr,
- uint64_t win_size, uint32_t omi,
- uint32_t snoopid, uint32_t stashid,
- uint32_t subwin_cnt)
- {
- struct paace *ppaace;
- if ((win_size & (win_size - 1)) || win_size < PAMU_PAGE_SIZE)
- return -1;
- if (win_addr & (win_size - 1))
- return -2;
- if (liodn > NUM_PPAACT_ENTRIES) {
- printf("Entries in PPACT not sufficient\n");
- return -3;
- }
- ppaace = &ppaact[liodn];
- /* window size is 2^(WSE+1) bytes */
- set_bf(ppaace->addr_bitfields, PPAACE_AF_WSE,
- map_addrspace_size_to_wse(win_size));
- pamu_setup_default_xfer_to_host_ppaace(ppaace);
- if (sizeof(phys_addr_t) > 4)
- ppaace->wbah = (u64)win_addr >> (PAMU_PAGE_SHIFT + 20);
- else
- ppaace->wbah = 0;
- set_bf(ppaace->addr_bitfields, PPAACE_AF_WBAL,
- (win_addr >> PAMU_PAGE_SHIFT));
- /* set up operation mapping if it's configured */
- if (omi < OME_NUMBER_ENTRIES) {
- set_bf(ppaace->impl_attr, PAACE_IA_OTM, PAACE_OTM_INDEXED);
- ppaace->op_encode.index_ot.omi = omi;
- } else if (~omi != 0) {
- return -3;
- }
- /* configure stash id */
- if (~stashid != 0)
- set_bf(ppaace->impl_attr, PAACE_IA_CID, stashid);
- /* configure snoop id */
- if (~snoopid != 0)
- ppaace->domain_attr.to_host.snpid = snoopid;
- if (subwin_cnt) {
- /* window count is 2^(WCE+1) bytes */
- set_bf(ppaace->impl_attr, PAACE_IA_WCE,
- map_subwindow_cnt_to_wce(subwin_cnt));
- set_bf(ppaace->addr_bitfields, PPAACE_AF_MW, 0x1);
- ppaace->fspi = fspi;
- fspi = fspi + DEFAULT_NUM_SUBWINDOWS - 1;
- } else {
- set_bf(ppaace->addr_bitfields, PAACE_AF_AP, PAACE_AP_PERMS_ALL);
- }
- asm volatile("sync" : : : "memory");
- /* Mark the ppace entry valid */
- ppaace->addr_bitfields |= PAACE_V_VALID;
- asm volatile("sync" : : : "memory");
- return 0;
- }
- static int pamu_config_spaace(uint32_t liodn,
- uint64_t subwin_size, uint64_t subwin_addr, uint64_t size,
- uint32_t omi, uint32_t snoopid, uint32_t stashid)
- {
- struct paace *paace;
- /* Align start addr of subwin to subwindoe size */
- uint64_t sec_addr = subwin_addr & ~(subwin_size - 1);
- uint64_t end_addr = subwin_addr + size;
- int size_shift = __ilog2_u64(subwin_size);
- uint64_t win_size = 0;
- uint32_t index, swse;
- unsigned long fspi_idx;
- /* Recalculate the size */
- size = end_addr - sec_addr;
- if (!subwin_size)
- return -1;
- if (liodn > NUM_PPAACT_ENTRIES) {
- printf("LIODN No programmed %d > no. of PPAACT entries %d\n",
- liodn, NUM_PPAACT_ENTRIES);
- return -1;
- }
- while (sec_addr < end_addr) {
- debug("sec_addr < end_addr is %llx < %llx\n", sec_addr,
- end_addr);
- paace = &ppaact[liodn];
- if (!paace)
- return -1;
- fspi_idx = paace->fspi;
- /* Calculating the win_size here as if we map in index 0,
- paace entry woudl need to be programmed for SWSE */
- win_size = end_addr - sec_addr;
- win_size = 1 << __ilog2_roundup_64(win_size);
- if (win_size > subwin_size)
- win_size = subwin_size;
- else if (win_size < PAMU_PAGE_SIZE)
- win_size = PAMU_PAGE_SIZE;
- debug("win_size is %llx\n", win_size);
- swse = map_addrspace_size_to_wse(win_size);
- index = sec_addr >> size_shift;
- if (index == 0) {
- set_bf(paace->win_bitfields, PAACE_WIN_SWSE, swse);
- set_bf(paace->addr_bitfields, PAACE_AF_AP,
- PAACE_AP_PERMS_ALL);
- sec_addr += subwin_size;
- continue;
- }
- paace = sec + fspi_idx + index - 1;
- debug("SPAACT:Writing at location %p, index %d\n", paace,
- index);
- pamu_setup_default_xfer_to_host_spaace(paace);
- set_bf(paace->addr_bitfields, SPAACE_AF_LIODN, liodn);
- set_bf(paace->addr_bitfields, PAACE_AF_AP, PAACE_AP_PERMS_ALL);
- /* configure snoop id */
- if (~snoopid != 0)
- paace->domain_attr.to_host.snpid = snoopid;
- if (paace->addr_bitfields & PAACE_V_VALID) {
- debug("Reached overlap condition\n");
- debug("%d < %d\n", get_bf(paace->win_bitfields,
- PAACE_WIN_SWSE), swse);
- if (get_bf(paace->win_bitfields, PAACE_WIN_SWSE) < swse)
- set_bf(paace->win_bitfields, PAACE_WIN_SWSE,
- swse);
- } else {
- set_bf(paace->win_bitfields, PAACE_WIN_SWSE, swse);
- }
- paace->addr_bitfields |= PAACE_V_VALID;
- sec_addr += subwin_size;
- }
- return 0;
- }
- int pamu_init(void)
- {
- u32 base_addr = CONFIG_SYS_PAMU_ADDR;
- struct ccsr_pamu *regs;
- u32 i = 0;
- u64 ppaact_phys, ppaact_lim, ppaact_size;
- u64 spaact_phys, spaact_lim, spaact_size;
- ppaact_size = sizeof(struct paace) * NUM_PPAACT_ENTRIES;
- spaact_size = sizeof(struct paace) * NUM_SPAACT_ENTRIES;
- /* Allocate space for Primary PAACT Table */
- #if (defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_PPAACT_ADDR))
- ppaact = (void *)CONFIG_SPL_PPAACT_ADDR;
- #else
- ppaact = memalign(PAMU_TABLE_ALIGNMENT, ppaact_size);
- if (!ppaact)
- return -1;
- #endif
- memset(ppaact, 0, ppaact_size);
- /* Allocate space for Secondary PAACT Table */
- #if (defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_SPAACT_ADDR))
- sec = (void *)CONFIG_SPL_SPAACT_ADDR;
- #else
- sec = memalign(PAMU_TABLE_ALIGNMENT, spaact_size);
- if (!sec)
- return -1;
- #endif
- memset(sec, 0, spaact_size);
- ppaact_phys = virt_to_phys((void *)ppaact);
- ppaact_lim = ppaact_phys + ppaact_size;
- spaact_phys = (uint64_t)virt_to_phys((void *)sec);
- spaact_lim = spaact_phys + spaact_size;
- /* Configure all PAMU's */
- for (i = 0; i < CONFIG_NUM_PAMU; i++) {
- regs = (struct ccsr_pamu *)base_addr;
- out_be32(®s->ppbah, ppaact_phys >> 32);
- out_be32(®s->ppbal, (uint32_t)ppaact_phys);
- out_be32(®s->pplah, (ppaact_lim) >> 32);
- out_be32(®s->pplal, (uint32_t)ppaact_lim);
- if (sec != NULL) {
- out_be32(®s->spbah, spaact_phys >> 32);
- out_be32(®s->spbal, (uint32_t)spaact_phys);
- out_be32(®s->splah, spaact_lim >> 32);
- out_be32(®s->splal, (uint32_t)spaact_lim);
- }
- asm volatile("sync" : : : "memory");
- base_addr += PAMU_OFFSET;
- }
- return 0;
- }
- void pamu_enable(void)
- {
- u32 i = 0;
- u32 base_addr = CONFIG_SYS_PAMU_ADDR;
- for (i = 0; i < CONFIG_NUM_PAMU; i++) {
- setbits_be32((void *)base_addr + PAMU_PCR_OFFSET,
- PAMU_PCR_PE);
- asm volatile("sync" : : : "memory");
- base_addr += PAMU_OFFSET;
- }
- }
- void pamu_reset(void)
- {
- u32 i = 0;
- u32 base_addr = CONFIG_SYS_PAMU_ADDR;
- struct ccsr_pamu *regs;
- for (i = 0; i < CONFIG_NUM_PAMU; i++) {
- regs = (struct ccsr_pamu *)base_addr;
- /* Clear PPAACT Base register */
- out_be32(®s->ppbah, 0);
- out_be32(®s->ppbal, 0);
- out_be32(®s->pplah, 0);
- out_be32(®s->pplal, 0);
- out_be32(®s->spbah, 0);
- out_be32(®s->spbal, 0);
- out_be32(®s->splah, 0);
- out_be32(®s->splal, 0);
- clrbits_be32((void *)regs + PAMU_PCR_OFFSET, PAMU_PCR_PE);
- asm volatile("sync" : : : "memory");
- base_addr += PAMU_OFFSET;
- }
- }
- void pamu_disable(void)
- {
- u32 i = 0;
- u32 base_addr = CONFIG_SYS_PAMU_ADDR;
- for (i = 0; i < CONFIG_NUM_PAMU; i++) {
- clrbits_be32((void *)base_addr + PAMU_PCR_OFFSET, PAMU_PCR_PE);
- asm volatile("sync" : : : "memory");
- base_addr += PAMU_OFFSET;
- }
- }
- static uint64_t find_max(uint64_t arr[], int num)
- {
- int i = 0;
- int max = 0;
- for (i = 1 ; i < num; i++)
- if (arr[max] < arr[i])
- max = i;
- return arr[max];
- }
- static uint64_t find_min(uint64_t arr[], int num)
- {
- int i = 0;
- int min = 0;
- for (i = 1 ; i < num; i++)
- if (arr[min] > arr[i])
- min = i;
- return arr[min];
- }
- static uint32_t get_win_cnt(uint64_t size)
- {
- uint32_t win_cnt = DEFAULT_NUM_SUBWINDOWS;
- while (win_cnt && (size/win_cnt) < PAMU_PAGE_SIZE)
- win_cnt >>= 1;
- return win_cnt;
- }
- int config_pamu(struct pamu_addr_tbl *tbl, int num_entries, uint32_t liodn)
- {
- int i = 0;
- int ret = 0;
- uint32_t num_sec_windows = 0;
- uint32_t num_windows = 0;
- uint64_t min_addr, max_addr;
- uint64_t size;
- uint64_t subwin_size;
- int sizebit;
- min_addr = find_min(tbl->start_addr, num_entries);
- max_addr = find_max(tbl->end_addr, num_entries);
- size = max_addr - min_addr + 1;
- if (!size)
- return -1;
- sizebit = __ilog2_roundup_64(size);
- size = 1 << sizebit;
- debug("min start_addr is %llx\n", min_addr);
- debug("max end_addr is %llx\n", max_addr);
- debug("size found is %llx\n", size);
- if (size < PAMU_PAGE_SIZE)
- size = PAMU_PAGE_SIZE;
- while (1) {
- min_addr = min_addr & ~(size - 1);
- if (min_addr + size > max_addr)
- break;
- size <<= 1;
- if (!size)
- return -1;
- }
- debug("PAACT :Base addr is %llx\n", min_addr);
- debug("PAACT : Size is %llx\n", size);
- num_windows = get_win_cnt(size);
- /* For a single window, no spaact entries are required
- * sec_sub_window count = 0 */
- if (num_windows > 1)
- num_sec_windows = num_windows;
- else
- num_sec_windows = 0;
- ret = pamu_config_ppaace(liodn, min_addr,
- size , -1, -1, -1, num_sec_windows);
- if (ret < 0)
- return ret;
- debug("configured ppace\n");
- if (num_sec_windows) {
- subwin_size = size >> count_lsb_zeroes(num_sec_windows);
- debug("subwin_size is %llx\n", subwin_size);
- for (i = 0; i < num_entries; i++) {
- ret = pamu_config_spaace(liodn,
- subwin_size, tbl->start_addr[i] - min_addr,
- tbl->size[i], -1, -1, -1);
- if (ret < 0)
- return ret;
- }
- }
- return ret;
- }
|