blob: 2147dd76bc89313f6fa13103316f85a07009f383 [file] [log] [blame]
/*
* Texas Instruments TCI6614 SoC Support
*
* Copyright (C) 2011 Texas Instruments
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation version 2.
*
* This program is distributed "as is" WITHOUT ANY WARRANTY of any
* kind, whether express or implied; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/err.h>
#include <linux/platform_device.h>
#include <asm/mach/map.h>
#include <mach/common.h>
#include <mach/time.h>
#include <mach/cputype.h>
#include <mach/psc.h>
#include <mach/cp_intc.h>
#include <mach/irqs.h>
#include <mach/gpio.h>
#include <mach/hardware.h>
#include <mach/cp_intd.h>
#include <mach/tci6614.h>
#include "clock.h"
#include "mux.h"
/* Base addresses for on-chip devices */
#define TCI6614_TIMER7_BASE 0x02270000
#define TCI6614_TIMER8_BASE 0x02280000
#define TCI6614_PLL_BASE 0x02310000
#define TCI6614_GPIO_BASE 0x02320000
#define TCI6614_PSC_BASE 0x02350000
#define TCI6614_CPINTC_BASE 0x0260c000
#define TCI6614_CPINTD_BASE 0x02610000
#define TCI6614_BOOT_CFG_BASE 0x02620000
#define TCI6614_AINTC_BASE 0x48200000
#define TCI6614_BOOT_CFG_DEVSTAT (TCI6614_BOOT_CFG_BASE + 0x20)
#define TCI6614_MAINPLL_CTL0 (TCI6614_BOOT_CFG_BASE + 0x328)
#define TCI6614_PLLCTRL_PLLM (TCI6614_PLL_BASE + 0x0110)
#define TCI6614_RSTMUX8 (TCI6614_BOOT_CFG_BASE + 0x0318)
#define TCI6614_DEFAULT_IN_CLK 50000000
#define MAINPLL_CTL0_PLLM_MASK 0x7F000
#define MAINPLL_CTL0_PLLM_SHIFT 6
#define MAINPLL_CTL0_PLLD_MASK 0x3f
#define PLLCTRL_PLLM_MASK 0x3f
#define RSTMUX8_OMODE_DEVICE_RESET 5
#define RSTMUX8_OMODE_DEVICE_RESET_SHIFT 1
#define RSTMUX8_OMODE_DEVICE_RESET_MASK (BIT(1) | BIT(2) | BIT(3))
#define RSTMUX8_LOCK_MASK BIT(0)
/* PSC control registers */
static u32 psc_regs[] = { TCI6614_PSC_BASE };
/* Host map for interrupt controller */
static u32 intc_host_map[] = { 0x01010000, 0x01010101, -1 };
static unsigned long tci6614_ref_clk_recalc(struct clk *clk)
{
void __iomem *devstat;
static unsigned long freq[] = { 50000000, 66666667, 80000000,
100000000, 156250000, 250000000,
312500000, 122880000 };
int sel;
devstat = ioremap(TCI6614_BOOT_CFG_DEVSTAT, 4);
if (WARN_ON(!devstat))
return TCI6614_DEFAULT_IN_CLK;
sel = (__raw_readl(devstat) >> 11) & 0x7;
iounmap(devstat);
return freq[sel];
}
static unsigned long tci6614_main_pll_clk_recalc(struct clk *clk)
{
unsigned long rate = 0;
u32 pllm, plld, postdiv = 2, val;
void __iomem *main_pll_ctl0, *pllctrl_pllm;
main_pll_ctl0 = ioremap(TCI6614_MAINPLL_CTL0, 4);
if (WARN_ON(!main_pll_ctl0))
return rate;
pllctrl_pllm = ioremap(TCI6614_PLLCTRL_PLLM, 4);
if (WARN_ON(!pllctrl_pllm))
return rate;
/* get bit0-5 of PLLM from PLLM PLL control register */
val = (__raw_readl(pllctrl_pllm) & PLLCTRL_PLLM_MASK);
pllm = (val & PLLCTRL_PLLM_MASK);
/* bit6-12 of PLLM is in Main PLL control register */
val = __raw_readl(main_pll_ctl0);
pllm |= ((val & MAINPLL_CTL0_PLLM_MASK) >> MAINPLL_CTL0_PLLM_SHIFT);
plld = (val & MAINPLL_CTL0_PLLD_MASK);
rate = clk->parent->rate;
rate /= (plld + 1);
rate = (rate * (pllm + 1));
rate /= postdiv;
printk(KERN_NOTICE "main_pll_clk rate is %ld, postdiv = %d, pllm = %d, plld = %d\n",
rate, postdiv, pllm, plld);
iounmap(main_pll_ctl0);
iounmap(pllctrl_pllm);
return rate;
}
static struct clk ref_clk = {
.name = "ref_clk",
.recalc = tci6614_ref_clk_recalc,
.flags = ALWAYS_ENABLED,
};
static struct pll_data main_pll_data = {
.num = 1,
.div_ratio_mask = 0xff,
.phys_base = TCI6614_PLL_BASE,
.flags = PLL_HAS_PREDIV | PLL_HAS_POSTDIV,
};
static struct clk main_pll = {
.name = "main_pll",
.parent = &ref_clk,
.recalc = tci6614_main_pll_clk_recalc,
.pll_data = &main_pll_data,
.flags = CLK_PLL | ALWAYS_ENABLED,
};
#define define_pll_div_clk(__pll, __div, __name) \
static struct clk __name = { \
.name = #__name, \
.parent = &__pll, \
.flags = CLK_PLL | ALWAYS_ENABLED, \
.div_reg = PLLDIV##__div, \
}
define_pll_div_clk(main_pll, 1, main_div_chip_clk1);
define_pll_div_clk(main_pll, 2, main_div_gem_trace_clk);
define_pll_div_clk(main_pll, 3, main_div_chip_clk2);
define_pll_div_clk(main_pll, 4, main_div_chip_clk3);
define_pll_div_clk(main_pll, 5, main_div_stm_clk);
define_pll_div_clk(main_pll, 6, main_div_emif_ptv_clk);
define_pll_div_clk(main_pll, 7, main_div_chip_clk6);
define_pll_div_clk(main_pll, 8, main_div_slowsys_clk);
define_pll_div_clk(main_pll, 9, main_div_chip_smreflex_clk);
define_pll_div_clk(main_pll, 10, main_div_chip_clk3_srio);
define_pll_div_clk(main_pll, 11, main_div_psc_clk6);
define_pll_div_clk(main_pll, 12, main_div_chip_dftclk4);
define_pll_div_clk(main_pll, 13, main_div_chip_dftclk8);
#define __lpsc_clk(cname, _parent, mod, flg, dom) \
static struct clk clk_##cname = { \
.name = #cname, \
.parent = &_parent, \
.lpsc = TCI6614_LPSC_##mod, \
.flags = flg, \
.domain = TCI6614_PD_##dom, \
}
#define lpsc_clk_enabled(cname, parent, mod) \
__lpsc_clk(cname, parent, mod, ALWAYS_ENABLED, ALWAYSON)
#define lpsc_clk(cname, parent, mod, dom) \
__lpsc_clk(cname, parent, mod, 0, dom)
/* Alawys on domains */
lpsc_clk_enabled(modrst0, main_div_chip_clk6, MODRST0);
lpsc_clk_enabled(src3_pwr, main_div_chip_smreflex_clk, SRC3_PWR);
lpsc_clk_enabled(emif4f, main_div_chip_clk1, EMIF4F);
lpsc_clk_enabled(monza_rst_ctrl, main_div_chip_clk1, MONZA_RST_CTRL);
/* There are 2 more clocks coming to some of the modules below and only
* one of the clock is mentioned as parent clock. Assume they are
* automatically enabled by gpsc
*/
lpsc_clk_enabled(timer0, clk_modrst0, MODRST0);
lpsc_clk_enabled(timer1, clk_modrst0, MODRST0);
lpsc_clk_enabled(uart0, clk_modrst0, MODRST0);
lpsc_clk_enabled(uart1, clk_modrst0, MODRST0);
lpsc_clk_enabled(aemif, clk_modrst0, MODRST0);
lpsc_clk_enabled(usim, clk_modrst0, MODRST0);
lpsc_clk_enabled(i2c, clk_modrst0, MODRST0);
lpsc_clk_enabled(spi, clk_modrst0, MODRST0);
lpsc_clk_enabled(gpio, clk_modrst0, MODRST0);
lpsc_clk_enabled(key_mgr, clk_modrst0, MODRST0);
/* SW controlled domains */
lpsc_clk(vusr, main_div_chip_clk2, VUSR, ALWAYSON);
lpsc_clk(vcp2_a, main_div_chip_clk3, VCP2_A, ALWAYSON);
lpsc_clk(debugss_trc, main_div_chip_clk3, DEBUGSS_TRC, DEBUG_TRC);
lpsc_clk(tetb_trc, main_div_chip_clk3, TETB_TRC, DEBUG_TRC);
lpsc_clk(pktproc, main_div_chip_clk3, PKTPROC, PASS);
lpsc_clk(crypto, main_div_chip_clk1, CRYPTO, PASS);
lpsc_clk(pciex, main_div_chip_clk2, PCIEX, PCIEX);
lpsc_clk(srio, main_div_chip_clk3_srio, SRIO, SRIO);
lpsc_clk(bcp, main_div_chip_clk3, BCP, BCP);
lpsc_clk(msmcsram, main_div_chip_clk2, MSMCSRAM, MSMCSRAM);
lpsc_clk(rac, main_div_chip_clk1, RAC, RAC_TAC);
lpsc_clk(tac, main_div_chip_clk3, TAC, RAC_TAC);
lpsc_clk(fftc, main_div_chip_clk3, FFTC, FFTC);
lpsc_clk(aif2, main_div_chip_clk3, AIF2, AIF2);
lpsc_clk(tcp3d, main_div_chip_clk2, TCP3D, TCP3D);
lpsc_clk(vcp2_b, main_div_chip_clk3, VCP2_B, VCP_BCD);
lpsc_clk(vcp2_c, main_div_chip_clk3, VCP2_C, VCP_BCD);
lpsc_clk(vcp2_d, main_div_chip_clk3, VCP2_D, VCP_BCD);
lpsc_clk(gem0, main_div_chip_clk1, GEM0, GEM0);
lpsc_clk(gem1, main_div_chip_clk1, GEM1, GEM1);
lpsc_clk(rsax2_1, main_div_chip_clk1, RSAX2_1, GEM1);
lpsc_clk(gem2, main_div_chip_clk1, GEM2, GEM2);
lpsc_clk(rsax2_0, main_div_chip_clk1, RSAX2_0, GEM2);
lpsc_clk(gem3, main_div_chip_clk1, GEM3, GEM3);
lpsc_clk(tcp3d_b, main_div_chip_clk2, TCP3D_B, TCP3D_B);
lpsc_clk(ethss, clk_pktproc, CPGMAC, PASS);
static struct clk clk_cpgmac = {
.parent = &clk_ethss,
};
static struct clk clk_mdio = {
.parent = &clk_ethss,
};
static struct clk clk_mdio_fck = {
.parent = &clk_mdio,
};
static struct clk clk_pa = {
.parent = &clk_pktproc,
};
static struct clk clk_pa_pktdma = {
.parent = &clk_pktproc,
};
static struct clk_lookup clks[] = {
CLK(NULL, "ref_clk", &ref_clk),
CLK(NULL, "main_pll", &main_pll),
CLK(NULL, "main_div_chip_clk1", &main_div_chip_clk1),
CLK(NULL, "main_div_gem_trace_clk", &main_div_gem_trace_clk),
CLK(NULL, "main_div_chip_clk2", &main_div_chip_clk2),
CLK(NULL, "main_div_chip_clk3", &main_div_chip_clk3),
CLK(NULL, "main_div_stm_clk", &main_div_stm_clk),
CLK(NULL, "main_div_emif_ptv_clk", &main_div_emif_ptv_clk),
CLK(NULL, "main_div_chip_clk6", &main_div_chip_clk6),
CLK(NULL, "main_div_slowsys_clk", &main_div_slowsys_clk),
CLK(NULL, "main_div_chip_smreflex_clk", &main_div_chip_smreflex_clk),
CLK(NULL, "main_div_chip_clk3_srio", &main_div_chip_clk3_srio),
CLK(NULL, "main_div_psc_clk6", &main_div_psc_clk6),
CLK(NULL, "main_div_chip_dftclk4", &main_div_chip_dftclk4),
CLK(NULL, "main_div_chip_dftclk8", &main_div_chip_dftclk8),
CLK(NULL, "clk_modrst0", &clk_modrst0),
CLK(NULL, "clk_src3_pwr", &clk_src3_pwr),
CLK(NULL, "clk_emif4f", &clk_emif4f),
CLK(NULL, "clk_vusr", &clk_vusr),
CLK(NULL, "clk_vcp2_a", &clk_vcp2_a),
CLK(NULL, "clk_debugss_trc", &clk_debugss_trc),
CLK(NULL, "clk_tetb_trc", &clk_tetb_trc),
CLK(NULL, "clk_pktproc", &clk_pktproc),
CLK("2004000.pktdma", NULL, &clk_pa_pktdma),
CLK("2090000.netcp", "clk_pa", &clk_pa),
CLK("2090000.netcp", "clk_ethss", &clk_ethss),
CLK("2090000.netcp", "clk_cpgmac", &clk_cpgmac),
CLK("20c0000.crypto", NULL, &clk_crypto),
CLK("2090300.mdio", NULL, &clk_mdio),
CLK("2090300.mdio", "fck", &clk_mdio_fck),
CLK(NULL, "clk_pciex", &clk_pciex),
CLK(NULL, "clk_srio", &clk_srio),
CLK(NULL, "clk_bcp", &clk_bcp),
CLK(NULL, "clk_monza_rst_ctrl", &clk_monza_rst_ctrl),
CLK(NULL, "clk_msmcsram", &clk_msmcsram),
CLK(NULL, "clk_rac", &clk_rac),
CLK(NULL, "clk_tac", &clk_tac),
CLK(NULL, "clk_fftc", &clk_fftc),
CLK(NULL, "clk_aif2", &clk_aif2),
CLK(NULL, "clk_tcp3d", &clk_tcp3d),
CLK(NULL, "clk_vcp2_b", &clk_vcp2_b),
CLK(NULL, "clk_vcp2_c", &clk_vcp2_c),
CLK(NULL, "clk_vcp2_d", &clk_vcp2_d),
CLK("keystone-rproc.0", NULL, &clk_gem0),
CLK("keystone-rproc.1", NULL, &clk_gem1),
CLK("keystone-rproc.2", NULL, &clk_gem2),
CLK("keystone-rproc.3", NULL, &clk_gem3),
CLK(NULL, "clk_rsax2_1", &clk_rsax2_1),
CLK(NULL, "clk_rsax2_0", &clk_rsax2_0),
CLK(NULL, "clk_tcp3d_b", &clk_tcp3d_b),
CLK(NULL, "timer0", &clk_timer0),
CLK("watchdog", NULL, &clk_timer1),
CLK(NULL, "uart0", &clk_uart0),
CLK(NULL, "uart1", &clk_uart1),
CLK(NULL, "aemif", &clk_aemif),
CLK(NULL, "usim", &clk_usim),
CLK("i2c_davinci.1", NULL, &clk_i2c),
CLK("spi_davinci.0", NULL, &clk_spi),
CLK(NULL, "gpio", &clk_gpio),
CLK(NULL, "key_mgr", &clk_key_mgr),
CLK(NULL, NULL, NULL),
};
/* FIQ are pri 0-1; otherwise 2-7, with 7 lowest priority */
static u8 aintc_irq_prios[TCI6614_N_AINTC_IRQ] = {
/* fill in default priority 0 */
[0 ... (TCI6614_N_AINTC_IRQ - 1)] = 0,
/* now override as needed, e.g. [xxx] = 5 */
};
/* Contents of JTAG ID register used to identify exact cpu type */
static struct davinci_id ids[] = {
{
.variant = 0x0,
.part_no = 0xb962,
.manufacturer = 0x017,
.cpu_id = DAVINCI_CPU_ID_TCI6614,
.name = "tci6614 rev 1.0",
},
{
/* For PG 1.3 */
.variant = 0x1,
.part_no = 0xb962,
.manufacturer = 0x017,
.cpu_id = DAVINCI_CPU_ID_TCI6614,
.name = "tci6614 rev 1.3",
},
};
static struct davinci_timer_instance timer_instance[2] = {
{
.base = TCI6614_TIMER7_BASE,
.bottom_irq = IRQ_TCI6614_TINT7L,
.top_irq = IRQ_TCI6614_TINT7H,
},
{
.base = TCI6614_TIMER8_BASE,
.bottom_irq = IRQ_TCI6614_TINT8L,
.top_irq = IRQ_TCI6614_TINT8H,
},
};
static struct davinci_timer_info timer_info = {
.timers = timer_instance,
.clockevent_id = T0_BOT,
.clocksource_id = T0_TOP,
};
/*
* TCI6614 platforms do not use the static mappings from Davinci
* IO_PHYS/IO_VIRT. This SOC's interesting MMRs are at different addresses,
* and changing IO_PHYS would break away from existing Davinci SOCs.
*
* The primary impact of the current model is that IO_ADDRESS() is not to be
* used to map registers on TCI6614.
*/
static struct map_desc io_desc[] = {
{
.virtual = IO_VIRT,
.pfn = __phys_to_pfn(TCI6614_IO_BASE),
.length = IO_SIZE,
.type = MT_DEVICE
},
};
static u32 aintc_to_intd_map[TCI6614_N_AINTC_IRQ] = {
[7] = IRQ_TCI6614_QM_INT_HIGH_1,
[8] = IRQ_TCI6614_IPC_H,
[9] = IRQ_TCI6614_QM_INT_HIGH_0,
[11] = IRQ_TCI6614_QM_INT_HIGH_2,
[12] = IRQ_TCI6614_QM_INT_HIGH_3,
[13] = IRQ_TCI6614_QM_INT_HIGH_4,
[14] = IRQ_TCI6614_QM_INT_HIGH_5,
[15] = IRQ_TCI6614_QM_INT_HIGH_6,
[16] = IRQ_TCI6614_QM_INT_HIGH_7,
[17] = IRQ_TCI6614_QM_INT_HIGH_8,
[18] = IRQ_TCI6614_QM_INT_HIGH_9,
[19] = IRQ_TCI6614_QM_INT_HIGH_10,
[20] = IRQ_TCI6614_QM_INT_HIGH_11,
[21] = IRQ_TCI6614_QM_INT_HIGH_12,
[22] = IRQ_TCI6614_QM_INT_HIGH_13,
[23] = IRQ_TCI6614_QM_INT_HIGH_14,
[24] = IRQ_TCI6614_QM_INT_HIGH_15,
[25] = IRQ_TCI6614_QM_INT_HIGH_16,
[26] = IRQ_TCI6614_QM_INT_HIGH_17,
[27] = IRQ_TCI6614_QM_INT_HIGH_18,
[28] = IRQ_TCI6614_QM_INT_HIGH_19,
[29] = IRQ_TCI6614_QM_INT_HIGH_20,
[30] = IRQ_TCI6614_QM_INT_HIGH_21,
[31] = IRQ_TCI6614_QM_INT_HIGH_22,
[32] = IRQ_TCI6614_QM_INT_HIGH_23,
[33] = IRQ_TCI6614_QM_INT_HIGH_24,
[34] = IRQ_TCI6614_QM_INT_HIGH_25,
[35] = IRQ_TCI6614_QM_INT_HIGH_26,
[36] = IRQ_TCI6614_QM_INT_HIGH_27,
[37] = IRQ_TCI6614_QM_INT_HIGH_28,
[38] = IRQ_TCI6614_QM_INT_HIGH_29,
[39] = IRQ_TCI6614_QM_INT_HIGH_30,
[40] = IRQ_TCI6614_QM_INT_HIGH_31,
[51] = IRQ_TCI6614_VUSR_INT,
[52] = IRQ_TCI6614_SEMERR7,
[53] = IRQ_TCI6614_SEMINT7,
[54] = IRQ_TCI6614_SRIO_INTDST20,
[55] = IRQ_TCI6614_SRIO_INTDST21,
[56] = IRQ_TCI6614_SRIO_INTDST22,
[57] = IRQ_TCI6614_SRIO_INTDST23,
[58] = IRQ_TCI6614_TINT4L,
[59] = IRQ_TCI6614_TINT4H,
[60] = IRQ_TCI6614_TINT5L,
[61] = IRQ_TCI6614_TINT5H,
[62] = IRQ_TCI6614_TINT6L,
[63] = IRQ_TCI6614_TINT6H,
[64] = IRQ_TCI6614_TINT7L,
[65] = IRQ_TCI6614_TINT7H,
[66] = IRQ_TCI6614_PCIE_ERR_INT,
[67] = IRQ_TCI6614_PCIE_PM_INT,
[68] = IRQ_TCI6614_PCIE_LEGACY_INTA,
[69] = IRQ_TCI6614_PCIE_LEGACY_INTB,
[70] = IRQ_TCI6614_PCIE_LEGACY_INTC,
[71] = IRQ_TCI6614_PCIE_LEGACY_INTD,
[72] = IRQ_TCI6614_PCIE_MSI_INT4,
[73] = IRQ_TCI6614_PCIE_MSI_INT5,
[74] = IRQ_TCI6614_PCIE_MSI_INT6,
[75] = IRQ_TCI6614_PCIE_MSI_INT7,
[76] = IRQ_TCI6614_TINT8L,
[77] = IRQ_TCI6614_TINT8H,
[78] = IRQ_TCI6614_TINT9L,
[79] = IRQ_TCI6614_TINT9H,
[80] = IRQ_TCI6614_TINT10L,
[81] = IRQ_TCI6614_TINT10H,
[82] = IRQ_TCI6614_TINT11L,
[83] = IRQ_TCI6614_TINT11H,
[84] = IRQ_TCI6614_TCP3D_A_REVT0,
[85] = IRQ_TCI6614_TCP3D_A_REVT1,
[86] = IRQ_TCI6614_TCP3D_B_REVT0,
[87] = IRQ_TCI6614_TCP3D_B_REVT1,
[88] = IRQ_TCI6614_CPU_3_1_TPCC_INT2,
[89] = IRQ_TCI6614_CPU_3_1_TPCC_INT6,
[90] = IRQ_TCI6614_CPU_3_2_TPCC_INT2,
[91] = IRQ_TCI6614_CPU_3_2_TPCC_INT6,
[92] = IRQ_TCI6614_CPU_2_TPCC_INT2,
[93] = IRQ_TCI6614_CPU_2_TPCC_INT6,
[127] = IRQ_TCI6614_WATCH_DOG_NMI,
};
static struct davinci_soc_info tci6614_soc_info = {
.io_desc = io_desc,
.io_desc_num = ARRAY_SIZE(io_desc),
.ids = ids,
.ids_num = ARRAY_SIZE(ids),
.jtag_id_reg = TCI6614_BOOT_CFG_BASE + 0x18,
.cpu_clks = clks,
.psc_bases = psc_regs,
.psc_bases_num = ARRAY_SIZE(psc_regs),
.intc_type = DAVINCI_INTC_TYPE_OMAP_AINTC,
.intc_base = TCI6614_AINTC_BASE,
.intc_irq_prios = aintc_irq_prios,
.intc_irq_num = TCI6614_N_AINTC_IRQ,
.intc_host_map = intc_host_map,
.intd_base = TCI6614_CPINTD_BASE,
.intd_irq_base = TCI6614_INTD_IRQ_BASE,
.intc_to_intd_map = aintc_to_intd_map,
.intd_irq_num = TCI6614_N_INTD_IRQ,
.gpio_base = TCI6614_GPIO_BASE,
.gpio_type = GPIO_TYPE_DAVINCI,
.gpio_num = TCI6614_N_GPIO,
.gpio_unbanked = TCI6614_N_GPIO,
.gpio_irq = IRQ_TCI6614_GPINT0,
.timer_info = &timer_info,
.serial_dev = &tci6614_serial_device,
};
void __init tci6614_init(void)
{
void __iomem *rstmux8;
u32 val;
davinci_common_init(&tci6614_soc_info);
/* Configure the RSTMUX8 register so that a WD output will trigger a
device reset
*/
rstmux8 = ioremap(TCI6614_RSTMUX8, 4);
WARN_ON(!rstmux8);
if (rstmux8) {
val = __raw_readl(rstmux8) & ~RSTMUX8_OMODE_DEVICE_RESET_MASK;
if (!(val & RSTMUX8_LOCK_MASK)) {
val |= (RSTMUX8_OMODE_DEVICE_RESET <<
RSTMUX8_OMODE_DEVICE_RESET_SHIFT);
__raw_writel(val, rstmux8);
} else
printk(KERN_NOTICE "Warning, can't write to RSTMUX8\n");
}
iounmap(rstmux8);
}
static void __iomem *cpintc_base;
static bool debug_cpintc;
#define debug_cpintc_irq(irq) (false)
#define CPINTC_REVISION 0x000
#define CPINTC_GLOBAL_ENABLE 0x010
#define CPINTC_STATUS_IDX_SET 0x020
#define CPINTC_STATUS_IDX_CLEAR 0x024
#define CPINTC_ENABLE_IDX_SET 0x028
#define CPINTC_ENABLE_IDX_CLEAR 0x02c
#define CPINTC_HOST_ENABLE_SET 0x034
#define CPINTC_HOST_ENABLE_CLEAR 0x038
#define CPINTC_GLOBAL_INDEX 0x080
#define CPINTC_STATUS_SET 0x200
#define CPINTC_STATUS_CLEAR 0x280
#define CPINTC_ENABLE_SET 0x300
#define CPINTC_ENABLE_CLEAR 0x380
#define CPINTC_CHANNEL_MAP 0x400
#define CPINTC_HOST_MAP 0x800
#define CPINTC_CHANS 8
#define CPINTC_REG(irq) (BIT_WORD(irq) << 2)
#define CPINTC_BIT(irq) (BIT_MASK(irq))
static inline u32 cpintc_readl(int offset)
{
u32 value = __raw_readl(cpintc_base + offset);
if (debug_cpintc)
printk(KERN_NOTICE \
"cpintc: read offset %x = %x\n", offset, value);
return value;
}
static inline void cpintc_writel(u32 value, int offset)
{
if (debug_cpintc)
printk(KERN_NOTICE \
"cpintc: write offset %x = %x\n", offset, value);
__raw_writel(value, cpintc_base + offset);
}
static void cpintc_mask_irq(struct irq_data *d)
{
unsigned int irq = d->irq;
irq -= TCI6614_CPINTC_IRQ_BASE;
if (debug_cpintc || debug_cpintc_irq(irq))
printk(KERN_NOTICE "cpintc: mask %d\n", irq);
cpintc_writel(irq, CPINTC_ENABLE_IDX_CLEAR);
}
void cpintc_unmask_irq(struct irq_data *d)
{
unsigned int irq = d->irq;
irq -= TCI6614_CPINTC_IRQ_BASE;
if (debug_cpintc || debug_cpintc_irq(irq))
printk(KERN_NOTICE "cpintc: unmask %d\n", irq);
cpintc_writel(irq, CPINTC_ENABLE_IDX_SET);
}
void cpintc_ack_irq(struct irq_data *d)
{
unsigned int irq = d->irq;
irq -= TCI6614_CPINTC_IRQ_BASE;
if (debug_cpintc || debug_cpintc_irq(irq))
printk(KERN_NOTICE "cpintc: ack %d\n", irq);
cpintc_writel(irq, CPINTC_STATUS_IDX_CLEAR);
}
bool cpintc_irq_pending(unsigned int irq)
{
bool enabled, pending;
irq -= TCI6614_CPINTC_IRQ_BASE;
enabled = (cpintc_readl(CPINTC_ENABLE_SET + CPINTC_REG(irq)) &
CPINTC_BIT(irq)) ? true : false;
pending = (cpintc_readl(CPINTC_STATUS_SET + CPINTC_REG(irq)) &
CPINTC_BIT(irq)) ? true : false;
if (debug_cpintc || debug_cpintc_irq(irq)) {
printk(KERN_NOTICE "cpintc: %d %s, %s\n", irq,
pending ? "pending" : "not pending",
enabled ? "enabled" : "not enabled");
}
return pending;
}
struct irq_chip cpintc_chip = {
.name = "CPINTC",
.irq_ack = cpintc_ack_irq,
.irq_mask = cpintc_mask_irq,
.irq_unmask = cpintc_unmask_irq,
};
void cpintc_irq_handler(unsigned irq, struct irq_desc *desc)
{
struct irq_chip *chip = irq_desc_get_chip(desc);
struct irq_data *irq_data = irq_desc_get_irq_data(desc);
int cpintc_irq;
if (debug_cpintc)
printk(KERN_NOTICE "cpintc: start irq %d\n", irq);
chip->irq_mask(irq_data);
chip->irq_ack(irq_data);
cpintc_irq = cpintc_readl(CPINTC_GLOBAL_INDEX);
if (cpintc_irq_pending(TCI6614_CPINTC_IRQ(cpintc_irq)))
generic_handle_irq(TCI6614_CPINTC_IRQ(cpintc_irq));
chip->irq_unmask(irq_data);
if (debug_cpintc)
printk(KERN_NOTICE "cpintc: end irq %d\n", irq);
}
void __init cpintc_init(void)
{
int i;
unsigned long rev;
cpintc_base = ioremap(TCI6614_CPINTC_BASE, SZ_8K);
BUG_ON(!cpintc_base);
rev = cpintc_readl(CPINTC_REVISION);
printk(KERN_INFO "IRQ: cpintc version %ld.%ld at %p\n",
(rev >> 8) & 0x3, rev & 0x3f, cpintc_base);
/* map all irqs to channel 0 */
for (i = 0; i < DIV_ROUND_UP(TCI6614_N_CPINTC_IRQ, 4); i++)
cpintc_writel(0, CPINTC_CHANNEL_MAP + (4 * i));
/* map all channels to host 0 */
for (i = 0; i < DIV_ROUND_UP(CPINTC_CHANS, 4); i++)
cpintc_writel(0, CPINTC_HOST_MAP + (4 * i));
cpintc_writel(0, CPINTC_HOST_ENABLE_SET);
for (i = 0; i < TCI6614_N_CPINTC_IRQ; i++) {
irq_set_chip_and_handler(TCI6614_CPINTC_IRQ(i),
&cpintc_chip, handle_edge_irq);
set_irq_flags(TCI6614_CPINTC_IRQ(i), IRQF_VALID | IRQF_PROBE);
}
for (i = IRQ_TCI6614_INTC3_OUT0; i <= IRQ_TCI6614_INTC3_OUT32; i++)
irq_set_chained_handler(i, cpintc_irq_handler);
cpintc_writel(1, CPINTC_GLOBAL_ENABLE);
}
void __init tci6614_intc_init(void)
{
omap_aintc_init();
cp_intd_init();
cpintc_init();
}