Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/arm/broadcom Add initial device support for the Bro...



details:   https://anonhg.NetBSD.org/src/rev/96600d33679b
branches:  trunk
changeset: 781316:96600d33679b
user:      matt <matt%NetBSD.org@localhost>
date:      Sat Sep 01 00:04:44 2012 +0000

description:
Add initial device support for the Broadcom BCM5301x family.

diffstat:

 sys/arch/arm/broadcom/bcm53xx_board.c |  534 +++++++++++++++++++++++++
 sys/arch/arm/broadcom/bcm53xx_cca.c   |  307 ++++++++++++++
 sys/arch/arm/broadcom/bcm53xx_ccb.c   |  183 ++++++++
 sys/arch/arm/broadcom/bcm53xx_eth.c   |  164 +++++++
 sys/arch/arm/broadcom/bcm53xx_i2c.c   |   87 ++++
 sys/arch/arm/broadcom/bcm53xx_idm.c   |  166 +++++++
 sys/arch/arm/broadcom/bcm53xx_intr.h  |  138 ++++++
 sys/arch/arm/broadcom/bcm53xx_mdio.c  |  166 +++++++
 sys/arch/arm/broadcom/bcm53xx_pax.c   |  156 +++++++
 sys/arch/arm/broadcom/bcm53xx_reg.h   |  709 ++++++++++++++++++++++++++++++++++
 sys/arch/arm/broadcom/bcm53xx_rng.c   |  200 +++++++++
 sys/arch/arm/broadcom/bcm53xx_sdhc.c  |  125 +++++
 sys/arch/arm/broadcom/bcm53xx_usb.c   |  281 +++++++++++++
 sys/arch/arm/broadcom/bcm53xx_var.h   |  119 +++++
 sys/arch/arm/broadcom/bcmgen_space.c  |  269 ++++++++++++
 sys/arch/arm/broadcom/files.bcm53xx   |   64 +++
 16 files changed, 3668 insertions(+), 0 deletions(-)

diffs (truncated from 3732 to 300 lines):

diff -r 0c31d55e0ac0 -r 96600d33679b sys/arch/arm/broadcom/bcm53xx_board.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/arch/arm/broadcom/bcm53xx_board.c     Sat Sep 01 00:04:44 2012 +0000
@@ -0,0 +1,534 @@
+/*     $NetBSD: bcm53xx_board.c,v 1.1 2012/09/01 00:04:44 matt Exp $   */
+/*-
+ * Copyright (c) 2012 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Matt Thomas of 3am Software Foundry.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "opt_broadcom.h"
+
+#define        _ARM32_BUS_DMA_PRIVATE
+
+#include <sys/cdefs.h>
+
+__KERNEL_RCSID(1, "$NetBSD: bcm53xx_board.c,v 1.1 2012/09/01 00:04:44 matt Exp $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/cpu.h>
+#include <sys/device.h>
+
+#include <prop/proplib.h>
+
+#define CRU_PRIVATE
+#define DDR_PRIVATE
+#define DMU_PRIVATE
+#define ARMCORE_PRIVATE
+
+#include <arm/cortex/a9tmr_var.h>
+#include <arm/mainbus/mainbus.h>
+
+#include <arm/broadcom/bcm53xx_reg.h>
+#include <arm/broadcom/bcm53xx_var.h>
+
+bus_space_tag_t bcm53xx_ioreg_bst = &bcmgen_bs_tag;
+bus_space_handle_t bcm53xx_ioreg_bsh;
+bus_space_tag_t bcm53xx_armcore_bst = &bcmgen_bs_tag;
+bus_space_handle_t bcm53xx_armcore_bsh;
+
+static struct cpu_softc cpu_softc;
+static struct bcm53xx_clock_info clk_info;
+
+struct arm32_bus_dma_tag bcm53xx_dma_tag = {
+       0,
+       0,
+       NULL,                   /* _cookie */
+       _bus_dmamap_create,
+       _bus_dmamap_destroy,
+       _bus_dmamap_load,
+       _bus_dmamap_load_mbuf,
+       _bus_dmamap_load_uio,
+       _bus_dmamap_load_raw,
+       _bus_dmamap_unload,
+       _bus_dmamap_sync,
+       NULL,                   /* sync_post */
+       _bus_dmamem_alloc,
+       _bus_dmamem_free,
+       _bus_dmamem_map,
+       _bus_dmamem_unmap,
+       _bus_dmamem_mmap
+};
+
+#ifdef BCM53XX_CONSOLE_EARLY
+#include <dev/ic/ns16550reg.h>
+#include <dev/ic/comreg.h>
+#include <dev/cons.h>
+
+static vaddr_t com_base;
+
+static inline uint32_t
+uart_read(bus_size_t o)
+{
+       return *(volatile uint8_t *)(com_base + o);
+}
+
+static inline void
+uart_write(bus_size_t o, uint32_t v)
+{
+       *(volatile uint8_t *)(com_base + o) = v;
+}
+
+static int
+bcm53xx_cngetc(dev_t dv)
+{
+        if ((uart_read(com_lsr) & LSR_RXRDY) == 0)
+               return -1;
+
+       return uart_read(com_data) & 0xff;
+}
+
+static void
+bcm53xx_cnputc(dev_t dv, int c)
+{
+       int timo = 150000;
+
+        while ((uart_read(com_lsr) & LSR_TXRDY) == 0 && --timo > 0)
+               ;
+
+       uart_write(com_data, c);
+
+       timo = 150000;
+        while ((uart_read(com_lsr) & LSR_TSRE) == 0 && --timo > 0)
+               ;
+}
+
+static struct consdev bcm53xx_earlycons = {
+       .cn_putc = bcm53xx_cnputc,
+       .cn_getc = bcm53xx_cngetc,
+       .cn_pollc = nullcnpollc,
+};
+#endif /* BCM53XX_CONSOLE_EARLY */
+
+psize_t
+bcm53xx_memprobe(void)
+{
+       bus_space_tag_t bst = bcm53xx_ioreg_bst;
+       bus_space_handle_t bsh = bcm53xx_ioreg_bsh;
+
+       /*
+        * First, let's read the magic DDR registers!
+        */
+       const uint32_t v01 = bus_space_read_4(bst, bsh, DDR_BASE + DDR_CTL_01);
+       const uint32_t v82 = bus_space_read_4(bst, bsh, DDR_BASE + DDR_CTL_82);
+       const uint32_t v86 = bus_space_read_4(bst, bsh, DDR_BASE + DDR_CTL_86);
+       const uint32_t v87 = bus_space_read_4(bst, bsh, DDR_BASE + DDR_CTL_87);
+
+       /*
+        * Calculate chip parameters
+        * */
+       const u_int rows = __SHIFTOUT(v01, CTL_01_MAX_ROW)
+           - __SHIFTOUT(v82, CTL_82_ROW_DIFF);
+       const u_int cols = __SHIFTOUT(v01, CTL_01_MAX_COL)
+           - __SHIFTOUT(v82, CTL_82_COL_DIFF);
+       const u_int banks_log2 = 3 - __SHIFTOUT(v82, CTL_82_BANK_DIFF);
+
+       /*
+        * For each chip select, increase the chip count if if is enabled.
+        */
+       const u_int max_chips = __SHIFTOUT(v01, CTL_01_MAX_CHIP_SEL);
+       u_int cs_map = __SHIFTOUT(v86, CTL_86_CS_MAP);
+       u_int chips = 0;
+
+       for (u_int i = 0; cs_map != 0 && i < max_chips; i++, cs_map >>= 1) {
+               chips += (cs_map & 1);
+       }
+
+       /* get log2(ddr width) */
+
+       const u_int ddr_width_log2 = (v87 & CTL_87_REDUC) ? 1 : 2;
+
+       /*
+        * Let's add up all the things that contribute to the size of a chip.
+        */
+       const u_int chip_size_log2 = cols + rows + banks_log2 + ddr_width_log2;
+
+       /*
+        * Now our memory size is simply the number of chip shifted by the
+        * log2(chip_size).
+        */
+       return (psize_t) chips << chip_size_log2;
+}
+
+static inline uint32_t
+bcm53xx_freq_calc(struct bcm53xx_clock_info *clk,
+       uint32_t pdiv, uint32_t ndiv_int, uint32_t ndiv_frac)
+{
+       if (ndiv_frac == 0 && pdiv == 1)
+               return ndiv_int * clk->clk_ref;
+
+       uint64_t freq64 = ((uint64_t)ndiv_int << 30) + ndiv_frac;
+       freq64 *= clk->clk_ref;
+       if (pdiv > 1)
+               freq64 /= pdiv;
+       return (uint32_t) (freq64 >> 30);
+}
+
+static uint32_t
+bcm53xx_value_wrap(uint32_t value, uint32_t mask)
+{
+       /*
+        * n is n except when n is 0 then n = mask + 1.
+        */
+       return ((__SHIFTOUT(value, mask) - 1) &  __SHIFTOUT(mask, mask)) + 1;
+}
+
+static void
+bcm53xx_genpll_clock_init(struct bcm53xx_clock_info *clk, uint32_t control5,
+       uint32_t control6, uint32_t control7)
+{
+       const uint32_t pdiv = bcm53xx_value_wrap(control6,
+           GENPLL_CONTROL6_PDIV);
+       const uint32_t ndiv_int = bcm53xx_value_wrap(control5,
+           GENPLL_CONTROL5_NDIV_INT);
+       const uint32_t ndiv_frac = __SHIFTOUT(control5,
+           GENPLL_CONTROL5_NDIV_FRAC);
+
+       clk->clk_genpll = bcm53xx_freq_calc(clk, pdiv, ndiv_int, ndiv_frac);
+
+       const uint32_t ch0_mdiv = bcm53xx_value_wrap(control6,
+           GENPLL_CONTROL6_CH0_MDIV);
+       const uint32_t ch1_mdiv = bcm53xx_value_wrap(control6,
+           GENPLL_CONTROL6_CH1_MDIV);
+       const uint32_t ch2_mdiv = bcm53xx_value_wrap(control6,
+           GENPLL_CONTROL6_CH2_MDIV);
+       const uint32_t ch3_mdiv = bcm53xx_value_wrap(control7,
+           GENPLL_CONTROL7_CH3_MDIV);
+
+       clk->clk_mac = clk->clk_genpll / ch0_mdiv;      // GENPLL CH0
+       clk->clk_robo = clk->clk_genpll / ch1_mdiv;     // GENPLL CH1
+       clk->clk_usb2 = clk->clk_genpll / ch2_mdiv;     // GENPLL CH2
+       clk->clk_iproc = clk->clk_genpll / ch3_mdiv;    // GENPLL CH3
+}
+
+static void
+bcm53xx_lcpll_clock_init(struct bcm53xx_clock_info *clk, uint32_t control1,
+       uint32_t control2)
+{
+       const uint32_t pdiv = bcm53xx_value_wrap(control1,
+           LCPLL_CONTROL1_PDIV);
+       const uint32_t ndiv_int = bcm53xx_value_wrap(control1,
+           LCPLL_CONTROL1_NDIV_INT);
+       const uint32_t ndiv_frac = __SHIFTOUT(control1,
+           LCPLL_CONTROL1_NDIV_FRAC);
+
+       clk->clk_lcpll = bcm53xx_freq_calc(clk, pdiv, ndiv_int, ndiv_frac);
+
+       const uint32_t ch0_mdiv = bcm53xx_value_wrap(control2,
+           LCPLL_CONTROL2_CH0_MDIV);
+       const uint32_t ch1_mdiv = bcm53xx_value_wrap(control2,
+           LCPLL_CONTROL2_CH1_MDIV);
+       const uint32_t ch2_mdiv = bcm53xx_value_wrap(control2,
+           LCPLL_CONTROL2_CH2_MDIV);
+       const uint32_t ch3_mdiv = bcm53xx_value_wrap(control2,
+           LCPLL_CONTROL2_CH3_MDIV);
+
+       clk->clk_pcie_ref = clk->clk_lcpll / ch0_mdiv;  // LCPLL CH0
+       clk->clk_sdio = clk->clk_lcpll / ch1_mdiv;      // LCPLL CH1
+       clk->clk_ddr_ref = clk->clk_lcpll / ch2_mdiv;   // LCPLL CH2
+       clk->clk_axi = clk->clk_lcpll / ch3_mdiv;       // LCPLL CH3
+}
+
+static void
+bcm53xx_usb_clock_init(struct bcm53xx_clock_info *clk, uint32_t usb2_control)
+{
+       const uint32_t pdiv = bcm53xx_value_wrap(usb2_control,
+           USB2_CONTROL_PDIV);
+       const uint32_t ndiv = bcm53xx_value_wrap(usb2_control,
+           USB2_CONTROL_NDIV_INT);
+
+       uint32_t usb_ref = (clk->clk_usb2 / pdiv) * ndiv; 
+       if (usb_ref != USB2_REF_CLK) {
+               /*
+                * USB Reference Clock isn't 1.92GHz.  So we need to modify
+                * USB2_CONTROL to produce it.
+                */
+               uint32_t new_ndiv = (USB2_REF_CLK / clk->clk_usb2) * pdiv;
+               usb2_control &= ~USB2_CONTROL_NDIV_INT;
+               usb2_control |= __SHIFTIN(new_ndiv, USB2_CONTROL_NDIV_INT);
+
+               // Allow Clocks to be modified
+               bus_space_write_4(bcm53xx_ioreg_bst, bcm53xx_ioreg_bsh,
+                   CRU_BASE + CRU_CLKSET_KEY, CRU_CLKSET_KEY_MAGIC);
+
+               // Update USB2 clock generator
+               bus_space_write_4(bcm53xx_ioreg_bst, bcm53xx_ioreg_bsh,
+                   CRU_BASE + CRU_USB2_CONTROL, usb2_control);
+
+               // Prevent Clock modification
+               bus_space_write_4(bcm53xx_ioreg_bst, bcm53xx_ioreg_bsh,
+                   CRU_BASE + CRU_CLKSET_KEY, 0);
+
+               usb_ref = (clk->clk_usb2 / pdiv) * new_ndiv; 
+       }
+



Home | Main Index | Thread Index | Old Index