void stmp3xxx_init_lcdif(void) { stmp3xxx_clearl(BM_LCDIF_CTRL_CLKGATE, REGS_LCDIF_BASE + HW_LCDIF_CTRL); /* Reset controller */ stmp3xxx_setl(BM_LCDIF_CTRL_SFTRST, REGS_LCDIF_BASE + HW_LCDIF_CTRL); udelay(10); /* Take controller out of reset */ stmp3xxx_clearl(BM_LCDIF_CTRL_SFTRST | BM_LCDIF_CTRL_CLKGATE, REGS_LCDIF_BASE + HW_LCDIF_CTRL); /* Setup the bus protocol */ stmp3xxx_clearl(BM_LCDIF_CTRL1_MODE86, REGS_LCDIF_BASE + HW_LCDIF_CTRL1); stmp3xxx_clearl(BM_LCDIF_CTRL1_BUSY_ENABLE, REGS_LCDIF_BASE + HW_LCDIF_CTRL1); /* Take display out of reset */ stmp3xxx_setl(BM_LCDIF_CTRL1_RESET, REGS_LCDIF_BASE + HW_LCDIF_CTRL1); /* VSYNC is an input by default */ stmp3xxx_setl(BM_LCDIF_VDCTRL0_VSYNC_OEB, REGS_LCDIF_BASE + HW_LCDIF_VDCTRL0); /* Reset display */ stmp3xxx_clearl(BM_LCDIF_CTRL1_RESET, REGS_LCDIF_BASE + HW_LCDIF_CTRL1); udelay(10); stmp3xxx_setl(BM_LCDIF_CTRL1_RESET, REGS_LCDIF_BASE + HW_LCDIF_CTRL1); udelay(10); }
static int stmp3xxx_set_irqtype(unsigned irq, unsigned type) { struct stmp3xxx_pinmux_bank *pm; unsigned gpio; int l, p; stmp3xxx_irq_to_gpio(irq, &pm, &gpio); switch (type) { case IRQ_TYPE_EDGE_RISING: l = 0; p = 1; break; case IRQ_TYPE_EDGE_FALLING: l = 0; p = 0; break; case IRQ_TYPE_LEVEL_HIGH: l = 1; p = 1; break; case IRQ_TYPE_LEVEL_LOW: l = 1; p = 0; break; default: pr_debug("%s: Incorrect GPIO interrupt type 0x%x\n", __func__, type); return -ENXIO; } if (l) stmp3xxx_setl(1 << gpio, pm->irqlevel); else stmp3xxx_clearl(1 << gpio, pm->irqlevel); if (p) stmp3xxx_setl(1 << gpio, pm->irqpolarity); else stmp3xxx_clearl(1 << gpio, pm->irqpolarity); return 0; }
void stmp3xxx_dma_resume(void) { stmp3xxx_clearl(BM_APBH_CTRL0_CLKGATE | BM_APBH_CTRL0_SFTRST, REGS_APBH_BASE + HW_APBH_CTRL0); stmp3xxx_clearl(BM_APBX_CTRL0_CLKGATE | BM_APBX_CTRL0_SFTRST, REGS_APBX_BASE + HW_APBX_CTRL0); }
static irqreturn_t stmp3xxx_timer_interrupt(int irq, void *dev_id) { struct clock_event_device *c = dev_id; /* timer 0 */ if (__raw_readl(REGS_TIMROT_BASE + HW_TIMROT_TIMCTRL0) & BM_TIMROT_TIMCTRLn_IRQ) { stmp3xxx_clearl(BM_TIMROT_TIMCTRLn_IRQ, REGS_TIMROT_BASE + HW_TIMROT_TIMCTRL0); c->event_handler(c); } /* timer 1 */ else if (__raw_readl(REGS_TIMROT_BASE + HW_TIMROT_TIMCTRL1) & BM_TIMROT_TIMCTRLn_IRQ) { stmp3xxx_clearl(BM_TIMROT_TIMCTRLn_IRQ, REGS_TIMROT_BASE + HW_TIMROT_TIMCTRL1); stmp3xxx_clearl(BM_TIMROT_TIMCTRLn_IRQ_EN, REGS_TIMROT_BASE + HW_TIMROT_TIMCTRL1); __raw_writel(0xFFFF, REGS_TIMROT_BASE + HW_TIMROT_TIMCOUNT1); } return IRQ_HANDLED; }
static void wdt_disable(void) { spin_lock(&stmp3xxx_wdt_io_lock); stmp3xxx_clearl(BV_RTC_PERSISTENT1_GENERAL__RTC_FORCE_UPDATER, REGS_RTC_BASE + HW_RTC_PERSISTENT1); stmp3xxx_clearl(BM_RTC_CTRL_WATCHDOGEN, REGS_RTC_BASE + HW_RTC_CTRL); spin_unlock(&stmp3xxx_wdt_io_lock); }
static void stmp3xxx_pin_mask_irq(unsigned irq) { struct stmp3xxx_pinmux_bank *pm; unsigned gpio; stmp3xxx_irq_to_gpio(irq, &pm, &gpio); stmp3xxx_clearl(1 << gpio, pm->irqen); stmp3xxx_clearl(1 << gpio, pm->pin2irq); }
void __init stmp3xxx_dma_init(void) { stmp3xxx_clearl(BM_APBH_CTRL0_CLKGATE | BM_APBH_CTRL0_SFTRST, REGS_APBH_BASE + HW_APBH_CTRL0); stmp3xxx_clearl(BM_APBX_CTRL0_CLKGATE | BM_APBX_CTRL0_SFTRST, REGS_APBX_BASE + HW_APBX_CTRL0); #ifdef CONFIG_CPU_FREQ cpufreq_register_notifier(&dma_cpufreq_nb.nb, CPUFREQ_TRANSITION_NOTIFIER); #endif /* CONFIG_CPU_FREQ */ }
void stmp3xxx_arch_dma_unfreeze(int channel) { unsigned chbit = 1 << STMP3XXX_DMA_CHANNEL(channel); switch (STMP3XXX_DMA_BUS(channel)) { case STMP3XXX_BUS_APBH: stmp3xxx_clearl(1 << chbit, REGS_APBH_BASE + HW_APBH_CTRL0); break; case STMP3XXX_BUS_APBX: stmp3xxx_clearl(1 << chbit, REGS_APBH_BASE + HW_APBH_CTRL0); break; } }
void stmp3xxx_arch_dma_clear_interrupt(int channel) { switch (STMP3XXX_DMA_BUS(channel)) { case STMP3XXX_BUS_APBH: stmp3xxx_clearl(1 << STMP3XXX_DMA_CHANNEL(channel), REGS_APBH_BASE + HW_APBH_CTRL1); break; case STMP3XXX_BUS_APBX: stmp3xxx_clearl(1 << STMP3XXX_DMA_CHANNEL(channel), REGS_APBX_BASE + HW_APBX_CTRL1); break; } }
void stmp3xxx_lcdif_stop(void) { if (stmp378x_lcd_master) { stmp3xxx_clearl(BM_LCDIF_CTRL_RUN, REGS_LCDIF_BASE + HW_LCDIF_CTRL); stmp3xxx_clearl(BM_LCDIF_CTRL_LCDIF_MASTER, REGS_LCDIF_BASE + HW_LCDIF_CTRL); udelay(100); } else { video_dma_descriptor[dma_chain_info_pos - 1].command->cmd |= BM_APBH_CHn_CMD_SEMAPHORE; udelay(100); } stmp3xxx_setl(BM_LCDIF_CTRL_CLKGATE, REGS_LCDIF_BASE + HW_LCDIF_CTRL); }
void stmp3xxx_pin_voltage(unsigned id, enum pin_voltage voltage, const char *label) { struct stmp3xxx_pinmux_bank *pbank; void __iomem *hwdrive; u32 shift; u32 bank, pin; pbank = stmp3xxx_pinmux_bank(id, &bank, &pin); pr_debug("%s: label %s bank %d pin %d voltage %d\n", __func__, label, bank, pin, voltage); hwdrive = pbank->hw_drive[pin / HW_DRIVE_PIN_NUM]; shift = (pin % HW_DRIVE_PIN_NUM) * HW_DRIVE_PIN_LEN; if (stmp3xxx_check_pin(id, label)) return; pr_debug("%s: changing 0x%x bit in 0x%p register\n", __func__, HW_DRIVE_PINV_MASK << shift, hwdrive); if (voltage == PIN_1_8V) stmp3xxx_clearl(HW_DRIVE_PINV_MASK << shift, hwdrive); else stmp3xxx_setl(HW_DRIVE_PINV_MASK << shift, hwdrive); }
void stmp3xxx_pin_strength(unsigned id, enum pin_strength strength, const char *label) { struct stmp3xxx_pinmux_bank *pbank; void __iomem *hwdrive; u32 shift, val; u32 bank, pin; pbank = stmp3xxx_pinmux_bank(id, &bank, &pin); pr_debug("%s: label %s bank %d pin %d strength %d\n", __func__, label, bank, pin, strength); hwdrive = pbank->hw_drive[pin / HW_DRIVE_PIN_NUM]; shift = (pin % HW_DRIVE_PIN_NUM) * HW_DRIVE_PIN_LEN; val = pbank->strengths[strength]; if (val == 0xff) { printk(KERN_WARNING "%s: strength is not supported for bank %d, caller %s", __func__, bank, label); return; } if (stmp3xxx_check_pin(id, label)) return; pr_debug("%s: writing 0x%x to 0x%p register\n", __func__, val << shift, hwdrive); stmp3xxx_clearl(HW_DRIVE_PINDRV_MASK << shift, hwdrive); stmp3xxx_setl(val << shift, hwdrive); }
void stmp3xxx_suspend_timer(void) { stmp3xxx_clearl(BM_TIMROT_TIMCTRLn_IRQ_EN | BM_TIMROT_TIMCTRLn_IRQ, REGS_TIMROT_BASE + HW_TIMROT_TIMCTRL0); stmp3xxx_setl(BM_TIMROT_ROTCTRL_CLKGATE, REGS_TIMROT_BASE + HW_TIMROT_ROTCTRL); }
static void free_bl(struct stmp3xxx_platform_bl_data *data) { stmp3xxx_clearl(BM_PWM_CTRL_PWM2_ENABLE, REGS_PWM_BASE + HW_PWM_CTRL); stmp3xxx_release_pin(PINID_PWM2, "lcd_hx8238a"); clk_disable(pwm_clk); clk_put(pwm_clk); }
static int __devinit stmp3xxx_wdt_probe(struct platform_device *pdev) { int ret = 0; if (heartbeat < 1 || heartbeat > MAX_HEARTBEAT) heartbeat = DEFAULT_HEARTBEAT; boot_status = __raw_readl(REGS_RTC_BASE + HW_RTC_PERSISTENT1) & BV_RTC_PERSISTENT1_GENERAL__RTC_FORCE_UPDATER; boot_status = !!boot_status; stmp3xxx_clearl(BV_RTC_PERSISTENT1_GENERAL__RTC_FORCE_UPDATER, REGS_RTC_BASE + HW_RTC_PERSISTENT1); wdt_disable(); /* disable for now */ ret = misc_register(&stmp3xxx_wdt_miscdev); if (ret < 0) { dev_err(&pdev->dev, "cannot register misc device\n"); return ret; } #ifdef CONFIG_DEBUG_PRINTK printk(KERN_INFO "stmp3xxx watchdog: initialized, heartbeat %d sec\n", heartbeat); #else ; #endif return ret; }
static int init_bl(struct stmp3xxx_platform_bl_data *data) { int ret = 0; pwm_clk = clk_get(NULL, "pwm"); if (IS_ERR(pwm_clk)) { ret = PTR_ERR(pwm_clk); goto out; } clk_enable(pwm_clk); stmp3xxx_reset_block(REGS_PWM_BASE, 1); ret = stmp3xxx_request_pin(PINID_PWM2, PIN_FUN1, "lcd_hx8238a"); if (ret) goto out_mux; stmp3xxx_pin_voltage(PINID_PWM2, PIN_12MA, "lcd_hx8238a"); stmp3xxx_pin_strength(PINID_PWM2, PIN_3_3V, "lcd_hx8238a"); stmp3xxx_clearl(BM_PWM_CTRL_PWM2_ENABLE, REGS_PWM_BASE + HW_PWM_CTRL); stmp3xxx_setl(BM_PWM_CTRL_PWM2_ANA_CTRL_ENABLE, REGS_PWM_BASE + HW_PWM_CTRL); __raw_writel(BF(10, PWM_ACTIVEn_INACTIVE) | BF(5, PWM_ACTIVEn_ACTIVE), REGS_PWM_BASE + HW_PWM_ACTIVEn(2)); __raw_writel(BF(1, PWM_PERIODn_CDIV) | /* divide by 2 */ BF(2, PWM_PERIODn_INACTIVE_STATE) | /* low */ BF(3, PWM_PERIODn_ACTIVE_STATE) | /* high */ BF(14, PWM_PERIODn_PERIOD), REGS_PWM_BASE + HW_PWM_PERIODn(2)); return 0; out_mux: clk_put(pwm_clk); out: return ret; }
void stmp3xxx_dma_set_alt_target(int channel, int function) { #if defined(CONFIG_ARCH_STMP37XX) unsigned bits = 4; #elif defined(CONFIG_ARCH_STMP378X) unsigned bits = 2; #else #error wrong arch #endif int shift = STMP3XXX_DMA_CHANNEL(channel) * bits; unsigned mask = (1<<bits) - 1; void __iomem *c; BUG_ON(function < 0 || function >= (1<<bits)); pr_debug("%s: channel = %d, using mask %x, " "shift = %d\n", __func__, channel, mask, shift); switch (STMP3XXX_DMA_BUS(channel)) { case STMP3XXX_BUS_APBH: c = REGS_APBH_BASE + HW_APBH_DEVSEL; break; case STMP3XXX_BUS_APBX: c = REGS_APBX_BASE + HW_APBX_DEVSEL; break; default: BUG(); } stmp3xxx_clearl(mask << shift, c); stmp3xxx_setl(mask << shift, c); }
void stmp37xx_circ_advance_active(struct stmp37xx_circ_dma_chain *chain, unsigned count) { void __iomem *c; u32 mask_clr, mask; BUG_ON(chain->free_count < count); chain->free_count -= count; chain->free_index += count; chain->free_index %= chain->total_count; chain->active_count += count; switch (chain->bus) { case STMP3XXX_BUS_APBH: c = REGS_APBH_BASE + HW_APBH_CHn_SEMA + 0x70 * chain->channel; mask_clr = BM_APBH_CHn_SEMA_INCREMENT_SEMA; mask = BF(count, APBH_CHn_SEMA_INCREMENT_SEMA); break; case STMP3XXX_BUS_APBX: c = REGS_APBX_BASE + HW_APBX_CHn_SEMA + 0x70 * chain->channel; mask_clr = BM_APBX_CHn_SEMA_INCREMENT_SEMA; mask = BF(count, APBX_CHn_SEMA_INCREMENT_SEMA); break; default: BUG(); return; } /* Set counting semaphore (kicks off transfer). Assumes peripheral has been set up correctly */ stmp3xxx_clearl(mask_clr, c); stmp3xxx_setl(mask, c); }
static int stmp3xxx_gpio_input(struct gpio_chip *chip, unsigned offset) { struct stmp3xxx_pinmux_bank *pm = to_pinmux_bank(chip); stmp3xxx_clearl(1 << offset, pm->hw_gpio_doe); return 0; }
static int blank_panel(int blank) { int ret = 0, count; switch (blank) { case FB_BLANK_NORMAL: case FB_BLANK_VSYNC_SUSPEND: case FB_BLANK_HSYNC_SUSPEND: case FB_BLANK_POWERDOWN: stmp3xxx_clearl(BM_LCDIF_CTRL_BYPASS_COUNT, REGS_LCDIF_BASE + HW_LCDIF_CTRL); /* Wait until current transfer is complete, max 30ms */ for (count = 30000; count > 0; count--) { if (__raw_readl(REGS_LCDIF_BASE + HW_LCDIF_STAT) & BM_LCDIF_STAT_TXFIFO_EMPTY) break; udelay(1); } break; case FB_BLANK_UNBLANK: stmp3xxx_setl(BM_LCDIF_CTRL_BYPASS_COUNT, REGS_LCDIF_BASE + HW_LCDIF_CTRL); break; default: ret = -EINVAL; } return ret; }
int usb_phy_enable(void) { u32 tmp; /* Reset USBPHY module */ stmp3xxx_setl(BM_USBPHY_CTRL_SFTRST, REGS_USBPHY_BASE + HW_USBPHY_CTRL); udelay(10); /* Remove CLKGATE and SFTRST */ stmp3xxx_clearl(BM_USBPHY_CTRL_CLKGATE | BM_USBPHY_CTRL_SFTRST, REGS_USBPHY_BASE + HW_USBPHY_CTRL); /* Turn on the USB clocks */ stmp3xxx_setl(BM_CLKCTRL_PLLCTRL0_EN_USB_CLKS, REGS_CLKCTRL_BASE + HW_CLKCTRL_PLLCTRL0); stmp3xxx_clearl(BM_DIGCTL_CTRL_USB_CLKGATE, REGS_DIGCTL_BASE + HW_DIGCTL_CTRL); /* set UTMI xcvr */ /* Workaround an IC issue for ehci driver: * when turn off root hub port power, EHCI set * PORTSC reserved bits to be 0, but PTW with 0 * means 8 bits tranceiver width, here change * it back to be 16 bits and do PHY diable and * then enable. */ tmp = __raw_readl(REGS_USBCTRL_BASE + HW_USBCTRL_PORTSC1) & ~PORTSC_PTS_MASK; tmp |= (PORTSC_PTS_UTMI | PORTSC_PTW); __raw_writel(tmp, REGS_USBCTRL_BASE + HW_USBCTRL_PORTSC1); /* Power up the PHY */ __raw_writel(0, REGS_USBPHY_BASE + HW_USBPHY_PWD); /* * Set precharge bit to cure overshoot problems at the * start of packets */ stmp3xxx_setl(1, REGS_USBPHY_BASE + HW_USBPHY_CTRL); #if defined(CONFIG_USB_EHCI_HCD) || defined(CONFIG_USB_EHCI_HCD_MODULE) /* enable disconnect detector */ /* enable disconnect detector must be after entry high speed mode*/ /*HW_USBPHY_CTRL_SET(BM_USBPHY_CTRL_ENHOSTDISCONDETECT); */ #endif return 0; }
static void stmp3xxx_gpio_set(struct gpio_chip *chip, unsigned offset, int v) { struct stmp3xxx_pinmux_bank *pm = to_pinmux_bank(chip); if (v) stmp3xxx_setl(1 << offset, pm->hw_gpio_out); else stmp3xxx_clearl(1 << offset, pm->hw_gpio_out); }
static void stmp3xxx_pin_ack_irq(unsigned irq) { u32 stat; struct stmp3xxx_pinmux_bank *pm; unsigned gpio; stmp3xxx_irq_to_gpio(irq, &pm, &gpio); stat = __raw_readl(pm->irqstat) & (1 << gpio); stmp3xxx_clearl(stat, pm->irqstat); }
/* * IRQ handling */ static void stmp37xx_ack_irq(unsigned int irq) { /* Disable IRQ */ stmp3xxx_clearl(0x04 << ((irq % 4) * 8), REGS_ICOLL_BASE + HW_ICOLL_PRIORITYn + irq / 4 * 0x10); /* ACK current interrupt */ __raw_writel(1, REGS_ICOLL_BASE + HW_ICOLL_LEVELACK); /* Barrier */ (void)__raw_readl(REGS_ICOLL_BASE + HW_ICOLL_STAT); }
void stmp3xxx_lcdif_dma_release(void) { int i; if (stmp378x_lcd_master) { stmp3xxx_clearl(BM_LCDIF_CTRL_LCDIF_MASTER, REGS_LCDIF_BASE + HW_LCDIF_CTRL); return; } for (i = 0; i < dma_chain_info_pos; i++) stmp3xxx_dma_free_command(STMP3XXX_DMA (LCD_DMA_CHANNEL, STMP3XXX_BUS_APBH), &video_dma_descriptor[i]); stmp3xxx_dma_release(STMP3XXX_DMA(LCD_DMA_CHANNEL, STMP3XXX_BUS_APBH)); dma_chain_info_pos = 0; }
void stmp3xxx_set_pin_type(unsigned id, enum pin_fun fun) { struct stmp3xxx_pinmux_bank *pbank; void __iomem *hwmux; u32 shift, val; u32 bank, pin; pbank = stmp3xxx_pinmux_bank(id, &bank, &pin); hwmux = pbank->hw_muxsel[pin / HW_MUXSEL_PIN_NUM]; shift = (pin % HW_MUXSEL_PIN_NUM) * HW_MUXSEL_PIN_LEN; val = pbank->functions[fun]; shift = (pin % HW_MUXSEL_PIN_NUM) * HW_MUXSEL_PIN_LEN; pr_debug("%s: writing 0x%x to 0x%p register\n", __func__, val << shift, hwmux); stmp3xxx_clearl(HW_MUXSEL_PINFUN_MASK << shift, hwmux); stmp3xxx_setl(val << shift, hwmux); }
void stmp3xxx_resume_timer(void) { stmp3xxx_clearl(BM_TIMROT_ROTCTRL_SFTRST | BM_TIMROT_ROTCTRL_CLKGATE, REGS_TIMROT_BASE + HW_TIMROT_ROTCTRL); __raw_writel( 8 << BP_TIMROT_TIMCTRLn_SELECT | /* 32 kHz */ BM_TIMROT_TIMCTRLn_RELOAD | BM_TIMROT_TIMCTRLn_UPDATE | BM_TIMROT_TIMCTRLn_IRQ_EN, REGS_TIMROT_BASE + HW_TIMROT_TIMCTRL0); __raw_writel( 8 << BP_TIMROT_TIMCTRLn_SELECT | /* 32 kHz */ BM_TIMROT_TIMCTRLn_RELOAD | BM_TIMROT_TIMCTRLn_UPDATE | BM_TIMROT_TIMCTRLn_IRQ_EN, REGS_TIMROT_BASE + HW_TIMROT_TIMCTRL1); __raw_writel(CLOCK_TICK_RATE / HZ - 1, REGS_TIMROT_BASE + HW_TIMROT_TIMCOUNT0); __raw_writel(0xFFFF, REGS_TIMROT_BASE + HW_TIMROT_TIMCOUNT1); }
static int blank_panel(int blank) { int ret = 0; switch (blank) { case FB_BLANK_NORMAL: case FB_BLANK_VSYNC_SUSPEND: case FB_BLANK_HSYNC_SUSPEND: case FB_BLANK_POWERDOWN: stmp3xxx_clearl(BM_LCDIF_CTRL_RUN, REGS_LCDIF_BASE + HW_LCDIF_CTRL); break; case FB_BLANK_UNBLANK: stmp3xxx_setl(BM_LCDIF_CTRL_RUN, REGS_LCDIF_BASE + HW_LCDIF_CTRL); break; default: ret = -EINVAL; } return ret; }
static void set_bl_intensity(struct stmp3xxx_platform_bl_data *data, struct backlight_device *bd, int suspended) { int intensity = bd->props.brightness; if (bd->props.power != FB_BLANK_UNBLANK) intensity = 0; if (bd->props.fb_blank != FB_BLANK_UNBLANK) intensity = 0; if (suspended) intensity = 0; stmp3xxx_clearl(BM_PWM_CTRL_PWM2_ENABLE, REGS_PWM_BASE + HW_PWM_CTRL); if (intensity) { HW_LRADC_CTRL2_CLR(BM_LRADC_CTRL2_BL_BRIGHTNESS); HW_LRADC_CTRL2_SET(BM_LRADC_CTRL2_BL_ENABLE | BM_LRADC_CTRL2_BL_MUX_SELECT | BF(intensity - 1, LRADC_CTRL2_BL_BRIGHTNESS)); stmp3xxx_setl(BM_PWM_CTRL_PWM2_ENABLE, REGS_PWM_BASE + HW_PWM_CTRL); } }
void stmp3xxx_pin_pullup(unsigned id, int enable, const char *label) { struct stmp3xxx_pinmux_bank *pbank; void __iomem *hwpull; u32 bank, pin; pbank = stmp3xxx_pinmux_bank(id, &bank, &pin); pr_debug("%s: label %s bank %d pin %d enable %d\n", __func__, label, bank, pin, enable); hwpull = pbank->hw_pull; if (stmp3xxx_check_pin(id, label)) return; pr_debug("%s: changing 0x%x bit in 0x%p register\n", __func__, 1 << pin, hwpull); if (enable) stmp3xxx_setl(1 << pin, hwpull); else stmp3xxx_clearl(1 << pin, hwpull); }