root/arch/arm/mach-mv78xx0/common.c

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

DEFINITIONS

This source file includes following definitions.
  1. mv78xx0_core_index
  2. get_hclk
  3. get_pclk_l2clk
  4. get_tclk
  5. mv78xx0_map_io
  6. clk_init
  7. mv78xx0_ehci0_init
  8. mv78xx0_ehci1_init
  9. mv78xx0_ehci2_init
  10. mv78xx0_ge00_init
  11. mv78xx0_ge01_init
  12. mv78xx0_ge10_init
  13. mv78xx0_ge11_init
  14. mv78xx0_i2c_init
  15. mv78xx0_sata_init
  16. mv78xx0_uart0_init
  17. mv78xx0_uart1_init
  18. mv78xx0_uart2_init
  19. mv78xx0_uart3_init
  20. mv78xx0_init_early
  21. mv78xx0_timer_init
  22. mv78xx0_id
  23. is_l2_writethrough
  24. mv78xx0_init
  25. mv78xx0_restart

   1 /*
   2  * arch/arm/mach-mv78xx0/common.c
   3  *
   4  * Core functions for Marvell MV78xx0 SoCs
   5  *
   6  * This file is licensed under the terms of the GNU General Public
   7  * License version 2.  This program is licensed "as is" without any
   8  * warranty of any kind, whether express or implied.
   9  */
  10 
  11 #include <linux/kernel.h>
  12 #include <linux/init.h>
  13 #include <linux/io.h>
  14 #include <linux/platform_device.h>
  15 #include <linux/serial_8250.h>
  16 #include <linux/ata_platform.h>
  17 #include <linux/clk-provider.h>
  18 #include <linux/ethtool.h>
  19 #include <asm/hardware/cache-feroceon-l2.h>
  20 #include <asm/mach/map.h>
  21 #include <asm/mach/time.h>
  22 #include <linux/platform_data/usb-ehci-orion.h>
  23 #include <linux/platform_data/mtd-orion_nand.h>
  24 #include <plat/time.h>
  25 #include <plat/common.h>
  26 #include <plat/addr-map.h>
  27 #include "mv78xx0.h"
  28 #include "bridge-regs.h"
  29 #include "common.h"
  30 
  31 static int get_tclk(void);
  32 
  33 /*****************************************************************************
  34  * Common bits
  35  ****************************************************************************/
  36 int mv78xx0_core_index(void)
  37 {
  38         u32 extra;
  39 
  40         /*
  41          * Read Extra Features register.
  42          */
  43         __asm__("mrc p15, 1, %0, c15, c1, 0" : "=r" (extra));
  44 
  45         return !!(extra & 0x00004000);
  46 }
  47 
  48 static int get_hclk(void)
  49 {
  50         int hclk;
  51 
  52         /*
  53          * HCLK tick rate is configured by DEV_D[7:5] pins.
  54          */
  55         switch ((readl(SAMPLE_AT_RESET_LOW) >> 5) & 7) {
  56         case 0:
  57                 hclk = 166666667;
  58                 break;
  59         case 1:
  60                 hclk = 200000000;
  61                 break;
  62         case 2:
  63                 hclk = 266666667;
  64                 break;
  65         case 3:
  66                 hclk = 333333333;
  67                 break;
  68         case 4:
  69                 hclk = 400000000;
  70                 break;
  71         default:
  72                 panic("unknown HCLK PLL setting: %.8x\n",
  73                         readl(SAMPLE_AT_RESET_LOW));
  74         }
  75 
  76         return hclk;
  77 }
  78 
  79 static void get_pclk_l2clk(int hclk, int core_index, int *pclk, int *l2clk)
  80 {
  81         u32 cfg;
  82 
  83         /*
  84          * Core #0 PCLK/L2CLK is configured by bits [13:8], core #1
  85          * PCLK/L2CLK by bits [19:14].
  86          */
  87         if (core_index == 0) {
  88                 cfg = (readl(SAMPLE_AT_RESET_LOW) >> 8) & 0x3f;
  89         } else {
  90                 cfg = (readl(SAMPLE_AT_RESET_LOW) >> 14) & 0x3f;
  91         }
  92 
  93         /*
  94          * Bits [11:8] ([17:14] for core #1) configure the PCLK:HCLK
  95          * ratio (1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5, 5.5, 6).
  96          */
  97         *pclk = ((u64)hclk * (2 + (cfg & 0xf))) >> 1;
  98 
  99         /*
 100          * Bits [13:12] ([19:18] for core #1) configure the PCLK:L2CLK
 101          * ratio (1, 2, 3).
 102          */
 103         *l2clk = *pclk / (((cfg >> 4) & 3) + 1);
 104 }
 105 
 106 static int get_tclk(void)
 107 {
 108         int tclk_freq;
 109 
 110         /*
 111          * TCLK tick rate is configured by DEV_A[2:0] strap pins.
 112          */
 113         switch ((readl(SAMPLE_AT_RESET_HIGH) >> 6) & 7) {
 114         case 1:
 115                 tclk_freq = 166666667;
 116                 break;
 117         case 3:
 118                 tclk_freq = 200000000;
 119                 break;
 120         default:
 121                 panic("unknown TCLK PLL setting: %.8x\n",
 122                         readl(SAMPLE_AT_RESET_HIGH));
 123         }
 124 
 125         return tclk_freq;
 126 }
 127 
 128 
 129 /*****************************************************************************
 130  * I/O Address Mapping
 131  ****************************************************************************/
 132 static struct map_desc mv78xx0_io_desc[] __initdata = {
 133         {
 134                 .virtual        = (unsigned long) MV78XX0_CORE_REGS_VIRT_BASE,
 135                 .pfn            = 0,
 136                 .length         = MV78XX0_CORE_REGS_SIZE,
 137                 .type           = MT_DEVICE,
 138         }, {
 139                 .virtual        = (unsigned long) MV78XX0_REGS_VIRT_BASE,
 140                 .pfn            = __phys_to_pfn(MV78XX0_REGS_PHYS_BASE),
 141                 .length         = MV78XX0_REGS_SIZE,
 142                 .type           = MT_DEVICE,
 143         },
 144 };
 145 
 146 void __init mv78xx0_map_io(void)
 147 {
 148         unsigned long phys;
 149 
 150         /*
 151          * Map the right set of per-core registers depending on
 152          * which core we are running on.
 153          */
 154         if (mv78xx0_core_index() == 0) {
 155                 phys = MV78XX0_CORE0_REGS_PHYS_BASE;
 156         } else {
 157                 phys = MV78XX0_CORE1_REGS_PHYS_BASE;
 158         }
 159         mv78xx0_io_desc[0].pfn = __phys_to_pfn(phys);
 160 
 161         iotable_init(mv78xx0_io_desc, ARRAY_SIZE(mv78xx0_io_desc));
 162 }
 163 
 164 
 165 /*****************************************************************************
 166  * CLK tree
 167  ****************************************************************************/
 168 static struct clk *tclk;
 169 
 170 static void __init clk_init(void)
 171 {
 172         tclk = clk_register_fixed_rate(NULL, "tclk", NULL, 0, get_tclk());
 173 
 174         orion_clkdev_init(tclk);
 175 }
 176 
 177 /*****************************************************************************
 178  * EHCI
 179  ****************************************************************************/
 180 void __init mv78xx0_ehci0_init(void)
 181 {
 182         orion_ehci_init(USB0_PHYS_BASE, IRQ_MV78XX0_USB_0, EHCI_PHY_NA);
 183 }
 184 
 185 
 186 /*****************************************************************************
 187  * EHCI1
 188  ****************************************************************************/
 189 void __init mv78xx0_ehci1_init(void)
 190 {
 191         orion_ehci_1_init(USB1_PHYS_BASE, IRQ_MV78XX0_USB_1);
 192 }
 193 
 194 
 195 /*****************************************************************************
 196  * EHCI2
 197  ****************************************************************************/
 198 void __init mv78xx0_ehci2_init(void)
 199 {
 200         orion_ehci_2_init(USB2_PHYS_BASE, IRQ_MV78XX0_USB_2);
 201 }
 202 
 203 
 204 /*****************************************************************************
 205  * GE00
 206  ****************************************************************************/
 207 void __init mv78xx0_ge00_init(struct mv643xx_eth_platform_data *eth_data)
 208 {
 209         orion_ge00_init(eth_data,
 210                         GE00_PHYS_BASE, IRQ_MV78XX0_GE00_SUM,
 211                         IRQ_MV78XX0_GE_ERR,
 212                         MV643XX_TX_CSUM_DEFAULT_LIMIT);
 213 }
 214 
 215 
 216 /*****************************************************************************
 217  * GE01
 218  ****************************************************************************/
 219 void __init mv78xx0_ge01_init(struct mv643xx_eth_platform_data *eth_data)
 220 {
 221         orion_ge01_init(eth_data,
 222                         GE01_PHYS_BASE, IRQ_MV78XX0_GE01_SUM,
 223                         MV643XX_TX_CSUM_DEFAULT_LIMIT);
 224 }
 225 
 226 
 227 /*****************************************************************************
 228  * GE10
 229  ****************************************************************************/
 230 void __init mv78xx0_ge10_init(struct mv643xx_eth_platform_data *eth_data)
 231 {
 232         u32 dev, rev;
 233 
 234         /*
 235          * On the Z0, ge10 and ge11 are internally connected back
 236          * to back, and not brought out.
 237          */
 238         mv78xx0_pcie_id(&dev, &rev);
 239         if (dev == MV78X00_Z0_DEV_ID) {
 240                 eth_data->phy_addr = MV643XX_ETH_PHY_NONE;
 241                 eth_data->speed = SPEED_1000;
 242                 eth_data->duplex = DUPLEX_FULL;
 243         }
 244 
 245         orion_ge10_init(eth_data, GE10_PHYS_BASE, IRQ_MV78XX0_GE10_SUM);
 246 }
 247 
 248 
 249 /*****************************************************************************
 250  * GE11
 251  ****************************************************************************/
 252 void __init mv78xx0_ge11_init(struct mv643xx_eth_platform_data *eth_data)
 253 {
 254         u32 dev, rev;
 255 
 256         /*
 257          * On the Z0, ge10 and ge11 are internally connected back
 258          * to back, and not brought out.
 259          */
 260         mv78xx0_pcie_id(&dev, &rev);
 261         if (dev == MV78X00_Z0_DEV_ID) {
 262                 eth_data->phy_addr = MV643XX_ETH_PHY_NONE;
 263                 eth_data->speed = SPEED_1000;
 264                 eth_data->duplex = DUPLEX_FULL;
 265         }
 266 
 267         orion_ge11_init(eth_data, GE11_PHYS_BASE, IRQ_MV78XX0_GE11_SUM);
 268 }
 269 
 270 /*****************************************************************************
 271  * I2C
 272  ****************************************************************************/
 273 void __init mv78xx0_i2c_init(void)
 274 {
 275         orion_i2c_init(I2C_0_PHYS_BASE, IRQ_MV78XX0_I2C_0, 8);
 276         orion_i2c_1_init(I2C_1_PHYS_BASE, IRQ_MV78XX0_I2C_1, 8);
 277 }
 278 
 279 /*****************************************************************************
 280  * SATA
 281  ****************************************************************************/
 282 void __init mv78xx0_sata_init(struct mv_sata_platform_data *sata_data)
 283 {
 284         orion_sata_init(sata_data, SATA_PHYS_BASE, IRQ_MV78XX0_SATA);
 285 }
 286 
 287 
 288 /*****************************************************************************
 289  * UART0
 290  ****************************************************************************/
 291 void __init mv78xx0_uart0_init(void)
 292 {
 293         orion_uart0_init(UART0_VIRT_BASE, UART0_PHYS_BASE,
 294                          IRQ_MV78XX0_UART_0, tclk);
 295 }
 296 
 297 
 298 /*****************************************************************************
 299  * UART1
 300  ****************************************************************************/
 301 void __init mv78xx0_uart1_init(void)
 302 {
 303         orion_uart1_init(UART1_VIRT_BASE, UART1_PHYS_BASE,
 304                          IRQ_MV78XX0_UART_1, tclk);
 305 }
 306 
 307 
 308 /*****************************************************************************
 309  * UART2
 310  ****************************************************************************/
 311 void __init mv78xx0_uart2_init(void)
 312 {
 313         orion_uart2_init(UART2_VIRT_BASE, UART2_PHYS_BASE,
 314                          IRQ_MV78XX0_UART_2, tclk);
 315 }
 316 
 317 /*****************************************************************************
 318  * UART3
 319  ****************************************************************************/
 320 void __init mv78xx0_uart3_init(void)
 321 {
 322         orion_uart3_init(UART3_VIRT_BASE, UART3_PHYS_BASE,
 323                          IRQ_MV78XX0_UART_3, tclk);
 324 }
 325 
 326 /*****************************************************************************
 327  * Time handling
 328  ****************************************************************************/
 329 void __init mv78xx0_init_early(void)
 330 {
 331         orion_time_set_base(TIMER_VIRT_BASE);
 332         if (mv78xx0_core_index() == 0)
 333                 mvebu_mbus_init("marvell,mv78xx0-mbus",
 334                                 BRIDGE_WINS_CPU0_BASE, BRIDGE_WINS_SZ,
 335                                 DDR_WINDOW_CPU0_BASE, DDR_WINDOW_CPU_SZ);
 336         else
 337                 mvebu_mbus_init("marvell,mv78xx0-mbus",
 338                                 BRIDGE_WINS_CPU1_BASE, BRIDGE_WINS_SZ,
 339                                 DDR_WINDOW_CPU1_BASE, DDR_WINDOW_CPU_SZ);
 340 }
 341 
 342 void __ref mv78xx0_timer_init(void)
 343 {
 344         orion_time_init(BRIDGE_VIRT_BASE, BRIDGE_INT_TIMER1_CLR,
 345                         IRQ_MV78XX0_TIMER_1, get_tclk());
 346 }
 347 
 348 
 349 /*****************************************************************************
 350  * General
 351  ****************************************************************************/
 352 static char * __init mv78xx0_id(void)
 353 {
 354         u32 dev, rev;
 355 
 356         mv78xx0_pcie_id(&dev, &rev);
 357 
 358         if (dev == MV78X00_Z0_DEV_ID) {
 359                 if (rev == MV78X00_REV_Z0)
 360                         return "MV78X00-Z0";
 361                 else
 362                         return "MV78X00-Rev-Unsupported";
 363         } else if (dev == MV78100_DEV_ID) {
 364                 if (rev == MV78100_REV_A0)
 365                         return "MV78100-A0";
 366                 else if (rev == MV78100_REV_A1)
 367                         return "MV78100-A1";
 368                 else
 369                         return "MV78100-Rev-Unsupported";
 370         } else if (dev == MV78200_DEV_ID) {
 371                 if (rev == MV78100_REV_A0)
 372                         return "MV78200-A0";
 373                 else
 374                         return "MV78200-Rev-Unsupported";
 375         } else {
 376                 return "Device-Unknown";
 377         }
 378 }
 379 
 380 static int __init is_l2_writethrough(void)
 381 {
 382         return !!(readl(CPU_CONTROL) & L2_WRITETHROUGH);
 383 }
 384 
 385 void __init mv78xx0_init(void)
 386 {
 387         int core_index;
 388         int hclk;
 389         int pclk;
 390         int l2clk;
 391 
 392         core_index = mv78xx0_core_index();
 393         hclk = get_hclk();
 394         get_pclk_l2clk(hclk, core_index, &pclk, &l2clk);
 395 
 396         printk(KERN_INFO "%s ", mv78xx0_id());
 397         printk("core #%d, ", core_index);
 398         printk("PCLK = %dMHz, ", (pclk + 499999) / 1000000);
 399         printk("L2 = %dMHz, ", (l2clk + 499999) / 1000000);
 400         printk("HCLK = %dMHz, ", (hclk + 499999) / 1000000);
 401         printk("TCLK = %dMHz\n", (get_tclk() + 499999) / 1000000);
 402 
 403         if (IS_ENABLED(CONFIG_CACHE_FEROCEON_L2))
 404                 feroceon_l2_init(is_l2_writethrough());
 405 
 406         /* Setup root of clk tree */
 407         clk_init();
 408 }
 409 
 410 void mv78xx0_restart(enum reboot_mode mode, const char *cmd)
 411 {
 412         /*
 413          * Enable soft reset to assert RSTOUTn.
 414          */
 415         writel(SOFT_RESET_OUT_EN, RSTOUTn_MASK);
 416 
 417         /*
 418          * Assert soft reset.
 419          */
 420         writel(SOFT_RESET, SYSTEM_SOFT_RESET);
 421 
 422         while (1)
 423                 ;
 424 }

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