|
@@ -19,7 +19,9 @@
|
|
|
#include <linux/device.h>
|
|
|
#include <linux/init.h>
|
|
|
#include <linux/io.h>
|
|
|
+#include <linux/platform_data/x86/clk-pmc-atom.h>
|
|
|
#include <linux/platform_data/x86/pmc_atom.h>
|
|
|
+#include <linux/platform_device.h>
|
|
|
#include <linux/pci.h>
|
|
|
#include <linux/seq_file.h>
|
|
|
|
|
@@ -36,6 +38,11 @@ struct pmc_reg_map {
|
|
|
const struct pmc_bit_map *pss;
|
|
|
};
|
|
|
|
|
|
+struct pmc_data {
|
|
|
+ const struct pmc_reg_map *map;
|
|
|
+ const struct pmc_clk *clks;
|
|
|
+};
|
|
|
+
|
|
|
struct pmc_dev {
|
|
|
u32 base_addr;
|
|
|
void __iomem *regmap;
|
|
@@ -49,6 +56,29 @@ struct pmc_dev {
|
|
|
static struct pmc_dev pmc_device;
|
|
|
static u32 acpi_base_addr;
|
|
|
|
|
|
+static const struct pmc_clk byt_clks[] = {
|
|
|
+ {
|
|
|
+ .name = "xtal",
|
|
|
+ .freq = 25000000,
|
|
|
+ .parent_name = NULL,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ .name = "pll",
|
|
|
+ .freq = 19200000,
|
|
|
+ .parent_name = "xtal",
|
|
|
+ },
|
|
|
+ {},
|
|
|
+};
|
|
|
+
|
|
|
+static const struct pmc_clk cht_clks[] = {
|
|
|
+ {
|
|
|
+ .name = "xtal",
|
|
|
+ .freq = 19200000,
|
|
|
+ .parent_name = NULL,
|
|
|
+ },
|
|
|
+ {},
|
|
|
+};
|
|
|
+
|
|
|
static const struct pmc_bit_map d3_sts_0_map[] = {
|
|
|
{"LPSS1_F0_DMA", BIT_LPSS1_F0_DMA},
|
|
|
{"LPSS1_F1_PWM1", BIT_LPSS1_F1_PWM1},
|
|
@@ -168,6 +198,16 @@ static const struct pmc_reg_map cht_reg_map = {
|
|
|
.pss = cht_pss_map,
|
|
|
};
|
|
|
|
|
|
+static const struct pmc_data byt_data = {
|
|
|
+ .map = &byt_reg_map,
|
|
|
+ .clks = byt_clks,
|
|
|
+};
|
|
|
+
|
|
|
+static const struct pmc_data cht_data = {
|
|
|
+ .map = &cht_reg_map,
|
|
|
+ .clks = cht_clks,
|
|
|
+};
|
|
|
+
|
|
|
static inline u32 pmc_reg_read(struct pmc_dev *pmc, int reg_offset)
|
|
|
{
|
|
|
return readl(pmc->regmap + reg_offset);
|
|
@@ -381,10 +421,37 @@ static int pmc_dbgfs_register(struct pmc_dev *pmc)
|
|
|
}
|
|
|
#endif /* CONFIG_DEBUG_FS */
|
|
|
|
|
|
+static int pmc_setup_clks(struct pci_dev *pdev, void __iomem *pmc_regmap,
|
|
|
+ const struct pmc_data *pmc_data)
|
|
|
+{
|
|
|
+ struct platform_device *clkdev;
|
|
|
+ struct pmc_clk_data *clk_data;
|
|
|
+
|
|
|
+ clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
|
|
|
+ if (!clk_data)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+ clk_data->base = pmc_regmap; /* offset is added by client */
|
|
|
+ clk_data->clks = pmc_data->clks;
|
|
|
+
|
|
|
+ clkdev = platform_device_register_data(&pdev->dev, "clk-pmc-atom",
|
|
|
+ PLATFORM_DEVID_NONE,
|
|
|
+ clk_data, sizeof(*clk_data));
|
|
|
+ if (IS_ERR(clkdev)) {
|
|
|
+ kfree(clk_data);
|
|
|
+ return PTR_ERR(clkdev);
|
|
|
+ }
|
|
|
+
|
|
|
+ kfree(clk_data);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
static int pmc_setup_dev(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|
|
{
|
|
|
struct pmc_dev *pmc = &pmc_device;
|
|
|
- const struct pmc_reg_map *map = (struct pmc_reg_map *)ent->driver_data;
|
|
|
+ const struct pmc_data *data = (struct pmc_data *)ent->driver_data;
|
|
|
+ const struct pmc_reg_map *map = data->map;
|
|
|
int ret;
|
|
|
|
|
|
/* Obtain ACPI base address */
|
|
@@ -413,6 +480,12 @@ static int pmc_setup_dev(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|
|
if (ret)
|
|
|
dev_warn(&pdev->dev, "debugfs register failed\n");
|
|
|
|
|
|
+ /* Register platform clocks - PMC_PLT_CLK [0..5] */
|
|
|
+ ret = pmc_setup_clks(pdev, pmc->regmap, data);
|
|
|
+ if (ret)
|
|
|
+ dev_warn(&pdev->dev, "platform clocks register failed: %d\n",
|
|
|
+ ret);
|
|
|
+
|
|
|
pmc->init = true;
|
|
|
return ret;
|
|
|
}
|
|
@@ -423,8 +496,8 @@ static int pmc_setup_dev(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|
|
* used by pci_match_id() call below.
|
|
|
*/
|
|
|
static const struct pci_device_id pmc_pci_ids[] = {
|
|
|
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_VLV_PMC), (kernel_ulong_t)&byt_reg_map },
|
|
|
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_CHT_PMC), (kernel_ulong_t)&cht_reg_map },
|
|
|
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_VLV_PMC), (kernel_ulong_t)&byt_data },
|
|
|
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_CHT_PMC), (kernel_ulong_t)&cht_data },
|
|
|
{ 0, },
|
|
|
};
|
|
|
|