root/arch/mips/ath25/ar5312.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ar5312_rst_reg_read
  2. ar5312_rst_reg_write
  3. ar5312_rst_reg_mask
  4. ar5312_ahb_err_handler
  5. ar5312_misc_irq_handler
  6. ar5312_misc_irq_unmask
  7. ar5312_misc_irq_mask
  8. ar5312_misc_irq_map
  9. ar5312_irq_dispatch
  10. ar5312_arch_init_irq
  11. ar5312_flash_init
  12. ar5312_init_devices
  13. ar5312_restart
  14. ar5312_cpu_frequency
  15. ar5312_sys_frequency
  16. ar5312_plat_time_init
  17. ar5312_plat_mem_setup
  18. ar5312_arch_init

   1 /*
   2  * This file is subject to the terms and conditions of the GNU General Public
   3  * License.  See the file "COPYING" in the main directory of this archive
   4  * for more details.
   5  *
   6  * Copyright (C) 2003 Atheros Communications, Inc.,  All Rights Reserved.
   7  * Copyright (C) 2006 FON Technology, SL.
   8  * Copyright (C) 2006 Imre Kaloz <kaloz@openwrt.org>
   9  * Copyright (C) 2006-2009 Felix Fietkau <nbd@openwrt.org>
  10  * Copyright (C) 2012 Alexandros C. Couloumbis <alex@ozo.com>
  11  */
  12 
  13 /*
  14  * Platform devices for Atheros AR5312 SoCs
  15  */
  16 
  17 #include <linux/init.h>
  18 #include <linux/kernel.h>
  19 #include <linux/bitops.h>
  20 #include <linux/irqdomain.h>
  21 #include <linux/interrupt.h>
  22 #include <linux/platform_device.h>
  23 #include <linux/mtd/physmap.h>
  24 #include <linux/reboot.h>
  25 #include <asm/bootinfo.h>
  26 #include <asm/reboot.h>
  27 #include <asm/time.h>
  28 
  29 #include <ath25_platform.h>
  30 
  31 #include "devices.h"
  32 #include "ar5312.h"
  33 #include "ar5312_regs.h"
  34 
  35 static void __iomem *ar5312_rst_base;
  36 static struct irq_domain *ar5312_misc_irq_domain;
  37 
  38 static inline u32 ar5312_rst_reg_read(u32 reg)
  39 {
  40         return __raw_readl(ar5312_rst_base + reg);
  41 }
  42 
  43 static inline void ar5312_rst_reg_write(u32 reg, u32 val)
  44 {
  45         __raw_writel(val, ar5312_rst_base + reg);
  46 }
  47 
  48 static inline void ar5312_rst_reg_mask(u32 reg, u32 mask, u32 val)
  49 {
  50         u32 ret = ar5312_rst_reg_read(reg);
  51 
  52         ret &= ~mask;
  53         ret |= val;
  54         ar5312_rst_reg_write(reg, ret);
  55 }
  56 
  57 static irqreturn_t ar5312_ahb_err_handler(int cpl, void *dev_id)
  58 {
  59         u32 proc1 = ar5312_rst_reg_read(AR5312_PROC1);
  60         u32 proc_addr = ar5312_rst_reg_read(AR5312_PROCADDR); /* clears error */
  61         u32 dma1 = ar5312_rst_reg_read(AR5312_DMA1);
  62         u32 dma_addr = ar5312_rst_reg_read(AR5312_DMAADDR);   /* clears error */
  63 
  64         pr_emerg("AHB interrupt: PROCADDR=0x%8.8x PROC1=0x%8.8x DMAADDR=0x%8.8x DMA1=0x%8.8x\n",
  65                  proc_addr, proc1, dma_addr, dma1);
  66 
  67         machine_restart("AHB error"); /* Catastrophic failure */
  68         return IRQ_HANDLED;
  69 }
  70 
  71 static struct irqaction ar5312_ahb_err_interrupt  = {
  72         .handler = ar5312_ahb_err_handler,
  73         .name    = "ar5312-ahb-error",
  74 };
  75 
  76 static void ar5312_misc_irq_handler(struct irq_desc *desc)
  77 {
  78         u32 pending = ar5312_rst_reg_read(AR5312_ISR) &
  79                       ar5312_rst_reg_read(AR5312_IMR);
  80         unsigned nr, misc_irq = 0;
  81 
  82         if (pending) {
  83                 struct irq_domain *domain = irq_desc_get_handler_data(desc);
  84 
  85                 nr = __ffs(pending);
  86                 misc_irq = irq_find_mapping(domain, nr);
  87         }
  88 
  89         if (misc_irq) {
  90                 generic_handle_irq(misc_irq);
  91                 if (nr == AR5312_MISC_IRQ_TIMER)
  92                         ar5312_rst_reg_read(AR5312_TIMER);
  93         } else {
  94                 spurious_interrupt();
  95         }
  96 }
  97 
  98 /* Enable the specified AR5312_MISC_IRQ interrupt */
  99 static void ar5312_misc_irq_unmask(struct irq_data *d)
 100 {
 101         ar5312_rst_reg_mask(AR5312_IMR, 0, BIT(d->hwirq));
 102 }
 103 
 104 /* Disable the specified AR5312_MISC_IRQ interrupt */
 105 static void ar5312_misc_irq_mask(struct irq_data *d)
 106 {
 107         ar5312_rst_reg_mask(AR5312_IMR, BIT(d->hwirq), 0);
 108         ar5312_rst_reg_read(AR5312_IMR); /* flush write buffer */
 109 }
 110 
 111 static struct irq_chip ar5312_misc_irq_chip = {
 112         .name           = "ar5312-misc",
 113         .irq_unmask     = ar5312_misc_irq_unmask,
 114         .irq_mask       = ar5312_misc_irq_mask,
 115 };
 116 
 117 static int ar5312_misc_irq_map(struct irq_domain *d, unsigned irq,
 118                                irq_hw_number_t hw)
 119 {
 120         irq_set_chip_and_handler(irq, &ar5312_misc_irq_chip, handle_level_irq);
 121         return 0;
 122 }
 123 
 124 static struct irq_domain_ops ar5312_misc_irq_domain_ops = {
 125         .map = ar5312_misc_irq_map,
 126 };
 127 
 128 static void ar5312_irq_dispatch(void)
 129 {
 130         u32 pending = read_c0_status() & read_c0_cause();
 131 
 132         if (pending & CAUSEF_IP2)
 133                 do_IRQ(AR5312_IRQ_WLAN0);
 134         else if (pending & CAUSEF_IP5)
 135                 do_IRQ(AR5312_IRQ_WLAN1);
 136         else if (pending & CAUSEF_IP6)
 137                 do_IRQ(AR5312_IRQ_MISC);
 138         else if (pending & CAUSEF_IP7)
 139                 do_IRQ(ATH25_IRQ_CPU_CLOCK);
 140         else
 141                 spurious_interrupt();
 142 }
 143 
 144 void __init ar5312_arch_init_irq(void)
 145 {
 146         struct irq_domain *domain;
 147         unsigned irq;
 148 
 149         ath25_irq_dispatch = ar5312_irq_dispatch;
 150 
 151         domain = irq_domain_add_linear(NULL, AR5312_MISC_IRQ_COUNT,
 152                                        &ar5312_misc_irq_domain_ops, NULL);
 153         if (!domain)
 154                 panic("Failed to add IRQ domain");
 155 
 156         irq = irq_create_mapping(domain, AR5312_MISC_IRQ_AHB_PROC);
 157         setup_irq(irq, &ar5312_ahb_err_interrupt);
 158 
 159         irq_set_chained_handler_and_data(AR5312_IRQ_MISC,
 160                                          ar5312_misc_irq_handler, domain);
 161 
 162         ar5312_misc_irq_domain = domain;
 163 }
 164 
 165 static struct physmap_flash_data ar5312_flash_data = {
 166         .width = 2,
 167 };
 168 
 169 static struct resource ar5312_flash_resource = {
 170         .start = AR5312_FLASH_BASE,
 171         .end = AR5312_FLASH_BASE + AR5312_FLASH_SIZE - 1,
 172         .flags = IORESOURCE_MEM,
 173 };
 174 
 175 static struct platform_device ar5312_physmap_flash = {
 176         .name = "physmap-flash",
 177         .id = 0,
 178         .dev.platform_data = &ar5312_flash_data,
 179         .resource = &ar5312_flash_resource,
 180         .num_resources = 1,
 181 };
 182 
 183 static void __init ar5312_flash_init(void)
 184 {
 185         void __iomem *flashctl_base;
 186         u32 ctl;
 187 
 188         flashctl_base = ioremap_nocache(AR5312_FLASHCTL_BASE,
 189                                         AR5312_FLASHCTL_SIZE);
 190 
 191         ctl = __raw_readl(flashctl_base + AR5312_FLASHCTL0);
 192         ctl &= AR5312_FLASHCTL_MW;
 193 
 194         /* fixup flash width */
 195         switch (ctl) {
 196         case AR5312_FLASHCTL_MW16:
 197                 ar5312_flash_data.width = 2;
 198                 break;
 199         case AR5312_FLASHCTL_MW8:
 200         default:
 201                 ar5312_flash_data.width = 1;
 202                 break;
 203         }
 204 
 205         /*
 206          * Configure flash bank 0.
 207          * Assume 8M window size. Flash will be aliased if it's smaller
 208          */
 209         ctl |= AR5312_FLASHCTL_E | AR5312_FLASHCTL_AC_8M | AR5312_FLASHCTL_RBLE;
 210         ctl |= 0x01 << AR5312_FLASHCTL_IDCY_S;
 211         ctl |= 0x07 << AR5312_FLASHCTL_WST1_S;
 212         ctl |= 0x07 << AR5312_FLASHCTL_WST2_S;
 213         __raw_writel(ctl, flashctl_base + AR5312_FLASHCTL0);
 214 
 215         /* Disable other flash banks */
 216         ctl = __raw_readl(flashctl_base + AR5312_FLASHCTL1);
 217         ctl &= ~(AR5312_FLASHCTL_E | AR5312_FLASHCTL_AC);
 218         __raw_writel(ctl, flashctl_base + AR5312_FLASHCTL1);
 219         ctl = __raw_readl(flashctl_base + AR5312_FLASHCTL2);
 220         ctl &= ~(AR5312_FLASHCTL_E | AR5312_FLASHCTL_AC);
 221         __raw_writel(ctl, flashctl_base + AR5312_FLASHCTL2);
 222 
 223         iounmap(flashctl_base);
 224 }
 225 
 226 void __init ar5312_init_devices(void)
 227 {
 228         struct ath25_boarddata *config;
 229 
 230         ar5312_flash_init();
 231 
 232         /* Locate board/radio config data */
 233         ath25_find_config(AR5312_FLASH_BASE, AR5312_FLASH_SIZE);
 234         config = ath25_board.config;
 235 
 236         /* AR2313 has CPU minor rev. 10 */
 237         if ((current_cpu_data.processor_id & 0xff) == 0x0a)
 238                 ath25_soc = ATH25_SOC_AR2313;
 239 
 240         /* AR2312 shares the same Silicon ID as AR5312 */
 241         else if (config->flags & BD_ISCASPER)
 242                 ath25_soc = ATH25_SOC_AR2312;
 243 
 244         /* Everything else is probably AR5312 or compatible */
 245         else
 246                 ath25_soc = ATH25_SOC_AR5312;
 247 
 248         platform_device_register(&ar5312_physmap_flash);
 249 
 250         switch (ath25_soc) {
 251         case ATH25_SOC_AR5312:
 252                 if (!ath25_board.radio)
 253                         return;
 254 
 255                 if (!(config->flags & BD_WLAN0))
 256                         break;
 257 
 258                 ath25_add_wmac(0, AR5312_WLAN0_BASE, AR5312_IRQ_WLAN0);
 259                 break;
 260         case ATH25_SOC_AR2312:
 261         case ATH25_SOC_AR2313:
 262                 if (!ath25_board.radio)
 263                         return;
 264                 break;
 265         default:
 266                 break;
 267         }
 268 
 269         if (config->flags & BD_WLAN1)
 270                 ath25_add_wmac(1, AR5312_WLAN1_BASE, AR5312_IRQ_WLAN1);
 271 }
 272 
 273 static void ar5312_restart(char *command)
 274 {
 275         /* reset the system */
 276         local_irq_disable();
 277         while (1)
 278                 ar5312_rst_reg_write(AR5312_RESET, AR5312_RESET_SYSTEM);
 279 }
 280 
 281 /*
 282  * This table is indexed by bits 5..4 of the CLOCKCTL1 register
 283  * to determine the predevisor value.
 284  */
 285 static unsigned clockctl1_predivide_table[4] __initdata = { 1, 2, 4, 5 };
 286 
 287 static unsigned __init ar5312_cpu_frequency(void)
 288 {
 289         u32 scratch, devid, clock_ctl1;
 290         u32 predivide_mask, multiplier_mask, doubler_mask;
 291         unsigned predivide_shift, multiplier_shift;
 292         unsigned predivide_select, predivisor, multiplier;
 293 
 294         /* Trust the bootrom's idea of cpu frequency. */
 295         scratch = ar5312_rst_reg_read(AR5312_SCRATCH);
 296         if (scratch)
 297                 return scratch;
 298 
 299         devid = ar5312_rst_reg_read(AR5312_REV);
 300         devid = (devid & AR5312_REV_MAJ) >> AR5312_REV_MAJ_S;
 301         if (devid == AR5312_REV_MAJ_AR2313) {
 302                 predivide_mask = AR2313_CLOCKCTL1_PREDIVIDE_MASK;
 303                 predivide_shift = AR2313_CLOCKCTL1_PREDIVIDE_SHIFT;
 304                 multiplier_mask = AR2313_CLOCKCTL1_MULTIPLIER_MASK;
 305                 multiplier_shift = AR2313_CLOCKCTL1_MULTIPLIER_SHIFT;
 306                 doubler_mask = AR2313_CLOCKCTL1_DOUBLER_MASK;
 307         } else { /* AR5312 and AR2312 */
 308                 predivide_mask = AR5312_CLOCKCTL1_PREDIVIDE_MASK;
 309                 predivide_shift = AR5312_CLOCKCTL1_PREDIVIDE_SHIFT;
 310                 multiplier_mask = AR5312_CLOCKCTL1_MULTIPLIER_MASK;
 311                 multiplier_shift = AR5312_CLOCKCTL1_MULTIPLIER_SHIFT;
 312                 doubler_mask = AR5312_CLOCKCTL1_DOUBLER_MASK;
 313         }
 314 
 315         /*
 316          * Clocking is derived from a fixed 40MHz input clock.
 317          *
 318          *  cpu_freq = input_clock * MULT (where MULT is PLL multiplier)
 319          *  sys_freq = cpu_freq / 4       (used for APB clock, serial,
 320          *                                 flash, Timer, Watchdog Timer)
 321          *
 322          *  cnt_freq = cpu_freq / 2       (use for CPU count/compare)
 323          *
 324          * So, for example, with a PLL multiplier of 5, we have
 325          *
 326          *  cpu_freq = 200MHz
 327          *  sys_freq = 50MHz
 328          *  cnt_freq = 100MHz
 329          *
 330          * We compute the CPU frequency, based on PLL settings.
 331          */
 332 
 333         clock_ctl1 = ar5312_rst_reg_read(AR5312_CLOCKCTL1);
 334         predivide_select = (clock_ctl1 & predivide_mask) >> predivide_shift;
 335         predivisor = clockctl1_predivide_table[predivide_select];
 336         multiplier = (clock_ctl1 & multiplier_mask) >> multiplier_shift;
 337 
 338         if (clock_ctl1 & doubler_mask)
 339                 multiplier <<= 1;
 340 
 341         return (40000000 / predivisor) * multiplier;
 342 }
 343 
 344 static inline unsigned ar5312_sys_frequency(void)
 345 {
 346         return ar5312_cpu_frequency() / 4;
 347 }
 348 
 349 void __init ar5312_plat_time_init(void)
 350 {
 351         mips_hpt_frequency = ar5312_cpu_frequency() / 2;
 352 }
 353 
 354 void __init ar5312_plat_mem_setup(void)
 355 {
 356         void __iomem *sdram_base;
 357         u32 memsize, memcfg, bank0_ac, bank1_ac;
 358         u32 devid;
 359 
 360         /* Detect memory size */
 361         sdram_base = ioremap_nocache(AR5312_SDRAMCTL_BASE,
 362                                      AR5312_SDRAMCTL_SIZE);
 363         memcfg = __raw_readl(sdram_base + AR5312_MEM_CFG1);
 364         bank0_ac = ATH25_REG_MS(memcfg, AR5312_MEM_CFG1_AC0);
 365         bank1_ac = ATH25_REG_MS(memcfg, AR5312_MEM_CFG1_AC1);
 366         memsize = (bank0_ac ? (1 << (bank0_ac + 1)) : 0) +
 367                   (bank1_ac ? (1 << (bank1_ac + 1)) : 0);
 368         memsize <<= 20;
 369         add_memory_region(0, memsize, BOOT_MEM_RAM);
 370         iounmap(sdram_base);
 371 
 372         ar5312_rst_base = ioremap_nocache(AR5312_RST_BASE, AR5312_RST_SIZE);
 373 
 374         devid = ar5312_rst_reg_read(AR5312_REV);
 375         devid >>= AR5312_REV_WMAC_MIN_S;
 376         devid &= AR5312_REV_CHIP;
 377         ath25_board.devid = (u16)devid;
 378 
 379         /* Clear any lingering AHB errors */
 380         ar5312_rst_reg_read(AR5312_PROCADDR);
 381         ar5312_rst_reg_read(AR5312_DMAADDR);
 382         ar5312_rst_reg_write(AR5312_WDT_CTRL, AR5312_WDT_CTRL_IGNORE);
 383 
 384         _machine_restart = ar5312_restart;
 385 }
 386 
 387 void __init ar5312_arch_init(void)
 388 {
 389         unsigned irq = irq_create_mapping(ar5312_misc_irq_domain,
 390                                           AR5312_MISC_IRQ_UART0);
 391 
 392         ath25_serial_setup(AR5312_UART0_BASE, irq, ar5312_sys_frequency());
 393 }

/* [<][>][^][v][top][bottom][index][help] */