init.c (3551B)
1 /* init.c 2 * 3 * Copyright 2011 Brian Swetland <swetland@frotz.net> 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 #include <fw/types.h> 19 #include <fw/io.h> 20 #include <arch/hardware.h> 21 22 void core_48mhz_init(void) { 23 /* switch to IRC if we aren't on it already */ 24 if ((readl(0x40048070) & 3) != 0) { 25 writel(0, 0x40048070); 26 writel(0, 0x40048074); 27 writel(1, 0x40048074); 28 } 29 30 /* power down SYS PLL */ 31 writel(readl(0x40048238) | (1 << 7), 0x40048238); 32 33 /* configure SYS PLL */ 34 writel(0x23, 0x40048008); /* MSEL=4, PSEL=2, OUT=48MHz */ 35 // writel(0x25, 0x40048008); /* MSEL=6, PSEL=2, OUT=72MHz */ 36 37 /* power up SYS PLL */ 38 writel(readl(0x40048238) & (~(1 << 7)), 0x40048238); 39 40 /* wait for SYS PLL to lock */ 41 while(!(readl(0x4004800c) & 1)) ; 42 43 44 /* select SYS PLL OUT for MAIN CLK */ 45 writel(3, 0x40048070); 46 writel(0, 0x40048074); 47 writel(1, 0x40048074); 48 49 /* select Main clock for USB CLK */ 50 writel(1, 0x400480C0); 51 writel(0, 0x400480C4); 52 writel(1, 0x400480C4); 53 54 /* set USB clock divider to 1 */ 55 writel(1, 0x400480C8); 56 57 /* clock to GPIO and MUX blocks */ 58 writel(readl(SYS_CLK_CTRL) | SYS_CLK_IOCON | SYS_CLK_GPIO, SYS_CLK_CTRL); 59 } 60 61 void ssp0_init(void) { 62 /* assert reset, disable clock */ 63 writel(readl(PRESETCTRL) & (~SSP0_RST_N), PRESETCTRL); 64 writel(0, SYS_DIV_SSP0); 65 66 /* enable SSP0 clock */ 67 writel(readl(SYS_CLK_CTRL) | SYS_CLK_SSP0, SYS_CLK_CTRL); 68 69 /* SSP0 PCLK = SYSCLK / 3 (16MHz) */ 70 writel(3, SYS_DIV_SSP0); 71 72 /* deassert reset */ 73 writel(readl(PRESETCTRL) | SSP0_RST_N, PRESETCTRL); 74 75 writel(2, SSP0_CPSR); /* prescale = PCLK/2 */ 76 writel(SSP_CR0_BITS(16) | SSP_CR0_FRAME_SPI | 77 SSP_CR0_CLK_HIGH | SSP_CR0_PHASE1 | 78 SSP_CR0_CLOCK_RATE(1), 79 SSP0_CR0); 80 writel(SSP_CR1_ENABLE | SSP_CR1_MASTER, SSP0_CR1); 81 82 /* configure io mux */ 83 /* XXX: this is board specific */ 84 writel(IOCON_SCK0_PIO2_11, IOCON_SCK0_LOC); 85 writel(IOCON_FUNC_1 | IOCON_DIGITAL, IOCON_PIO0_8); /* MISO */ 86 writel(IOCON_FUNC_1 | IOCON_DIGITAL, IOCON_PIO0_9); /* MOSI */ 87 writel(IOCON_FUNC_1 | IOCON_DIGITAL, IOCON_PIO2_11); /* SCK */ 88 } 89 90 static struct { 91 u16 khz; 92 u16 div; 93 } ssp_clocks[] = { 94 { 24000, 1, }, 95 { 12000, 2, }, 96 { 8000, 3, }, 97 { 6000, 4, }, 98 { 4000, 6, }, 99 { 3000, 8, }, 100 { 2000, 12, }, 101 { 1000, 24, }, 102 }; 103 104 unsigned ssp0_set_clock(unsigned khz) { 105 int n; 106 if (khz < 1000) 107 khz = 1000; 108 for (n = 0; n < (sizeof(ssp_clocks)/sizeof(ssp_clocks[0])); n++) { 109 if (ssp_clocks[n].khz <= khz) { 110 writel(ssp_clocks[n].div, SYS_DIV_SSP0); 111 return ssp_clocks[n].khz; 112 } 113 } 114 return 0; 115 } 116 117