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