/* linux/drivers/mfd/sm501.c
*
* Copyright (C) 2006 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
* Vincent Sanders <vince@simtec.co.uk>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* SM501 MFD driver
*/
#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/sm501.h>
#include <linux/sm501-regs.h>
#include <asm/io.h>
struct sm501_device {
struct list_head list;
struct platform_device pdev;
};
struct sm501_devdata {
spinlock_t reg_lock;
struct mutex clock_lock;
struct list_head devices;
struct device *dev;
struct resource *io_res;
struct resource *mem_res;
struct resource *regs_claim;
struct sm501_platdata *platdata;
int unit_power[20];
unsigned int pdev_id;
unsigned int irq;
void __iomem *regs;
};
#define MHZ (1000 * 1000)
#ifdef DEBUG
static const unsigned int misc_div[] = {
[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,
};
static const unsigned int px_div[] = {
[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, const unsigned int *dtab)
{
if (val & selbit)
pll2 = 288 * MHZ;
return pll2 / dtab[(val >> lshft) & mask];
}
#define fmt_freq(x) ((x) / MHZ), ((x) % MHZ), (x)
/* sm501_dump_clk
*
* Print out the current clock configuration for the device
*/
static void sm501_dump_clk(struct sm501_devdata *sm)
{
unsigned long