#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/list.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/pci.h>
#include <linux/platform_data/i2c-gpio.h>
#include <linux/gpio/driver.h>
#include <linux/gpio/machine.h>
#include <linux/slab.h>
#include <linux/sm501.h>
#include <linux/sm501-regs.h>
#include <linux/serial_8250.h>
#include <linux/io.h>
struct sm501_device { … };
struct sm501_gpio;
#ifdef CONFIG_MFD_SM501_GPIO
#include <linux/gpio.h>
struct sm501_gpio_chip { … };
struct sm501_gpio { … };
#else
struct sm501_gpio {
};
#endif
struct sm501_devdata { … };
#define MHZ …
#ifdef DEBUG
static const unsigned int div_tab[] = {
[0] = 1,
[1] = 2,
[2] = 4,
[3] = 8,
[4] = 16,
[5] = 32,
[6] = 64,
[7] = 128,
[8] = 3,
[9] = 6,
[10] = 12,
[11] = 24,
[12] = 48,
[13] = 96,
[14] = 192,
[15] = 384,
[16] = 5,
[17] = 10,
[18] = 20,
[19] = 40,
[20] = 80,
[21] = 160,
[22] = 320,
[23] = 604,
};
static unsigned long decode_div(unsigned long pll2, unsigned long val,
unsigned int lshft, unsigned int selbit,
unsigned long mask)
{
if (val & selbit)
pll2 = 288 * MHZ;
return pll2 / div_tab[(val >> lshft) & mask];
}
#define fmt_freq …
static void sm501_dump_clk(struct sm501_devdata *sm)
{
unsigned long misct = smc501_readl(sm->regs + SM501_MISC_TIMING);
unsigned long pm0 = smc501_readl(sm->regs + SM501_POWER_MODE_0_CLOCK);
unsigned long pm1 = smc501_readl(sm->regs + SM501_POWER_MODE_1_CLOCK);
unsigned long pmc = smc501_readl(sm->regs + SM501_POWER_MODE_CONTROL);
unsigned long sdclk0, sdclk1;
unsigned long pll2 = 0;
switch (misct & 0x30) {
case 0x00:
pll2 = 336 * MHZ;
break;
case 0x10:
pll2 = 288 * MHZ;
break;
case 0x20:
pll2 = 240 * MHZ;
break;
case 0x30:
pll2 = 192 * MHZ;
break;
}
sdclk0 = (misct & (1<<12)) ? pll2 : 288 * MHZ;
sdclk0 /= div_tab[((misct >> 8) & 0xf)];
sdclk1 = (misct & (1<<20)) ? pll2 : 288 * MHZ;
sdclk1 /= div_tab[((misct >> 16) & 0xf)];
dev_dbg(sm->dev, "MISCT=%08lx, PM0=%08lx, PM1=%08lx\n",
misct, pm0, pm1);
dev_dbg(sm->dev, "PLL2 = %ld.%ld MHz (%ld), SDCLK0=%08lx, SDCLK1=%08lx\n",
fmt_freq(pll2), sdclk0, sdclk1);
dev_dbg(sm->dev, "SDRAM: PM0=%ld, PM1=%ld\n", sdclk0, sdclk1);
dev_dbg(sm->dev, "PM0[%c]: "
"P2 %ld.%ld MHz (%ld), V2 %ld.%ld (%ld), "
"M %ld.%ld (%ld), MX1 %ld.%ld (%ld)\n",
(pmc & 3 ) == 0 ? '*' : '-',
fmt_freq(decode_div(pll2, pm0, 24, 1<<29, 31)),
fmt_freq(decode_div(pll2, pm0, 16, 1<<20, 15)),
fmt_freq(decode_div(pll2, pm0, 8, 1<<12, 15)),
fmt_freq(decode_div(pll2, pm0, 0, 1<<4, 15)));
dev_dbg(sm->dev, "PM1[%c]: "
"P2 %ld.%ld MHz (%ld), V2 %ld.%ld (%ld), "
"M %ld.%ld (%ld), MX1 %ld.%ld (%ld)\n",
(pmc & 3 ) == 1 ? '*' : '-',
fmt_freq(decode_div(pll2, pm1, 24, 1<<29, 31)),
fmt_freq(decode_div(pll2, pm1, 16, 1<<20, 15)),
fmt_freq(decode_div(pll2, pm1, 8, 1<<12, 15)),
fmt_freq(decode_div(pll2, pm1, 0, 1<<4, 15)));
}
static void sm501_dump_regs(struct sm501_devdata *sm)
{
void __iomem *regs = sm->regs;
dev_info(sm->dev, "System Control %08x\n",
smc501_readl(regs + SM501_SYSTEM_CONTROL));
dev_info(sm->dev, "Misc Control %08x\n",
smc501_readl(regs + SM501_MISC_CONTROL));
dev_info(sm->dev, "GPIO Control Low %08x\n",
smc501_readl(regs + SM501_GPIO31_0_CONTROL));
dev_info(sm->dev, "GPIO Control Hi %08x\n",
smc501_readl(regs + SM501_GPIO63_32_CONTROL));
dev_info(sm->dev, "DRAM Control %08x\n",
smc501_readl(regs + SM501_DRAM_CONTROL));
dev_info(sm->dev, "Arbitration Ctrl %08x\n",
smc501_readl(regs + SM501_ARBTRTN_CONTROL));
dev_info(sm->dev, "Misc Timing %08x\n",
smc501_readl(regs + SM501_MISC_TIMING));
}
static void sm501_dump_gate(struct sm501_devdata *sm)
{
dev_info(sm->dev, "CurrentGate %08x\n",
smc501_readl(sm->regs + SM501_CURRENT_GATE));
dev_info(sm->dev, "CurrentClock %08x\n",
smc501_readl(sm->regs + SM501_CURRENT_CLOCK));
dev_info(sm->dev, "PowerModeControl %08x\n",
smc501_readl(sm->regs + SM501_POWER_MODE_CONTROL));
}
#else
static inline void sm501_dump_gate(struct sm501_devdata *sm) { … }
static inline void sm501_dump_regs(struct sm501_devdata *sm) { … }
static inline void sm501_dump_clk(struct sm501_devdata *sm) { … }
#endif
static void sm501_sync_regs(struct sm501_devdata *sm)
{ … }
static inline void sm501_mdelay(struct sm501_devdata *sm, unsigned int delay)
{ … }
int sm501_misc_control(struct device *dev,
unsigned long set, unsigned long clear)
{ … }
EXPORT_SYMBOL_GPL(…);
unsigned long sm501_modify_reg(struct device *dev,
unsigned long reg,
unsigned long set,
unsigned long clear)
{ … }
EXPORT_SYMBOL_GPL(…);
int sm501_unit_power(struct device *dev, unsigned int unit, unsigned int to)
{ … }
EXPORT_SYMBOL_GPL(…);
struct sm501_clock { … };
static int sm501_calc_clock(unsigned long freq,
struct sm501_clock *clock,
int max_div,
unsigned long mclk,
long *best_diff)
{ … }
static unsigned long sm501_calc_pll(unsigned long freq,
struct sm501_clock *clock,
int max_div)
{ … }
static unsigned long sm501_select_clock(unsigned long freq,
struct sm501_clock *clock,
int max_div)
{ … }
unsigned long sm501_set_clock(struct device *dev,
int clksrc,
unsigned long req_freq)
{ … }
EXPORT_SYMBOL_GPL(…);
unsigned long sm501_find_clock(struct device *dev,
int clksrc,
unsigned long req_freq)
{ … }
EXPORT_SYMBOL_GPL(…);
static struct sm501_device *to_sm_device(struct platform_device *pdev)
{ … }
static void sm501_device_release(struct device *dev)
{ … }
static struct platform_device *
sm501_create_subdev(struct sm501_devdata *sm, char *name,
unsigned int res_count, unsigned int platform_data_size)
{ … }
static int sm501_register_device(struct sm501_devdata *sm,
struct platform_device *pdev)
{ … }
static void sm501_create_subio(struct sm501_devdata *sm,
struct resource *res,
resource_size_t offs,
resource_size_t size)
{ … }
static void sm501_create_mem(struct sm501_devdata *sm,
struct resource *res,
resource_size_t *offs,
resource_size_t size)
{ … }
static void sm501_create_irq(struct sm501_devdata *sm,
struct resource *res)
{ … }
static int sm501_register_usbhost(struct sm501_devdata *sm,
resource_size_t *mem_avail)
{ … }
static void sm501_setup_uart_data(struct sm501_devdata *sm,
struct plat_serial8250_port *uart_data,
unsigned int offset)
{ … }
static int sm501_register_uart(struct sm501_devdata *sm, int devices)
{ … }
static int sm501_register_display(struct sm501_devdata *sm,
resource_size_t *mem_avail)
{ … }
#ifdef CONFIG_MFD_SM501_GPIO
static inline struct sm501_devdata *sm501_gpio_to_dev(struct sm501_gpio *gpio)
{ … }
static int sm501_gpio_get(struct gpio_chip *chip, unsigned offset)
{ … }
static void sm501_gpio_ensure_gpio(struct sm501_gpio_chip *smchip,
unsigned long bit)
{ … }
static void sm501_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
{ … }
static int sm501_gpio_input(struct gpio_chip *chip, unsigned offset)
{ … }
static int sm501_gpio_output(struct gpio_chip *chip,
unsigned offset, int value)
{ … }
static const struct gpio_chip gpio_chip_template = …;
static int sm501_gpio_register_chip(struct sm501_devdata *sm,
struct sm501_gpio *gpio,
struct sm501_gpio_chip *chip)
{ … }
static int sm501_register_gpio(struct sm501_devdata *sm)
{ … }
static void sm501_gpio_remove(struct sm501_devdata *sm)
{ … }
static inline int sm501_gpio_isregistered(struct sm501_devdata *sm)
{ … }
#else
static inline int sm501_register_gpio(struct sm501_devdata *sm)
{
return 0;
}
static inline void sm501_gpio_remove(struct sm501_devdata *sm)
{
}
static inline int sm501_gpio_isregistered(struct sm501_devdata *sm)
{
return 0;
}
#endif
static int sm501_register_gpio_i2c_instance(struct sm501_devdata *sm,
struct sm501_platdata_gpio_i2c *iic)
{ … }
static int sm501_register_gpio_i2c(struct sm501_devdata *sm,
struct sm501_platdata *pdata)
{ … }
static ssize_t dbg_regs_show(struct device *dev,
struct device_attribute *attr, char *buff)
{ … }
static DEVICE_ATTR_RO(dbg_regs);
static inline void sm501_init_reg(struct sm501_devdata *sm,
unsigned long reg,
struct sm501_reg_init *r)
{ … }
static void sm501_init_regs(struct sm501_devdata *sm,
struct sm501_initdata *init)
{ … }
static int sm501_check_clocks(struct sm501_devdata *sm)
{ … }
static unsigned int sm501_mem_local[] = …;
static int sm501_init_dev(struct sm501_devdata *sm)
{ … }
static int sm501_plat_probe(struct platform_device *dev)
{ … }
static void sm501_set_power(struct sm501_devdata *sm, int on)
{ … }
static int sm501_plat_suspend(struct platform_device *pdev, pm_message_t state)
{ … }
static int sm501_plat_resume(struct platform_device *pdev)
{ … }
static struct sm501_initdata sm501_pci_initdata = …;
static struct sm501_platdata_fbsub sm501_pdata_fbsub = …;
static struct sm501_platdata_fb sm501_fb_pdata = …;
static struct sm501_platdata sm501_pci_platdata = …;
static int sm501_pci_probe(struct pci_dev *dev,
const struct pci_device_id *id)
{ … }
static void sm501_remove_sub(struct sm501_devdata *sm,
struct sm501_device *smdev)
{ … }
static void sm501_dev_remove(struct sm501_devdata *sm)
{ … }
static void sm501_pci_remove(struct pci_dev *dev)
{ … }
static void sm501_plat_remove(struct platform_device *dev)
{ … }
static const struct pci_device_id sm501_pci_tbl[] = …;
MODULE_DEVICE_TABLE(pci, sm501_pci_tbl);
static struct pci_driver sm501_pci_driver = …;
MODULE_ALIAS(…) …;
static const struct of_device_id of_sm501_match_tbl[] = …;
MODULE_DEVICE_TABLE(of, of_sm501_match_tbl);
static struct platform_driver sm501_plat_driver = …;
static int __init sm501_base_init(void)
{ … }
static void __exit sm501_base_exit(void)
{ … }
module_init(…) …;
module_exit(sm501_base_exit);
MODULE_DESCRIPTION(…) …;
MODULE_AUTHOR(…) …;
MODULE_LICENSE(…) …;