0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/clk-provider.h>
0009 #include <linux/io.h>
0010 #include <linux/of.h>
0011 #include <linux/of_address.h>
0012 #include <linux/reset-controller.h>
0013 #include <linux/slab.h>
0014 #include <linux/spinlock.h>
0015
0016 static DEFINE_SPINLOCK(ve_lock);
0017
0018 #define SUN4I_VE_ENABLE 31
0019 #define SUN4I_VE_DIVIDER_SHIFT 16
0020 #define SUN4I_VE_DIVIDER_WIDTH 3
0021 #define SUN4I_VE_RESET 0
0022
0023
0024
0025
0026
0027 struct ve_reset_data {
0028 void __iomem *reg;
0029 spinlock_t *lock;
0030 struct reset_controller_dev rcdev;
0031 };
0032
0033 static int sunxi_ve_reset_assert(struct reset_controller_dev *rcdev,
0034 unsigned long id)
0035 {
0036 struct ve_reset_data *data = container_of(rcdev,
0037 struct ve_reset_data,
0038 rcdev);
0039 unsigned long flags;
0040 u32 reg;
0041
0042 spin_lock_irqsave(data->lock, flags);
0043
0044 reg = readl(data->reg);
0045 writel(reg & ~BIT(SUN4I_VE_RESET), data->reg);
0046
0047 spin_unlock_irqrestore(data->lock, flags);
0048
0049 return 0;
0050 }
0051
0052 static int sunxi_ve_reset_deassert(struct reset_controller_dev *rcdev,
0053 unsigned long id)
0054 {
0055 struct ve_reset_data *data = container_of(rcdev,
0056 struct ve_reset_data,
0057 rcdev);
0058 unsigned long flags;
0059 u32 reg;
0060
0061 spin_lock_irqsave(data->lock, flags);
0062
0063 reg = readl(data->reg);
0064 writel(reg | BIT(SUN4I_VE_RESET), data->reg);
0065
0066 spin_unlock_irqrestore(data->lock, flags);
0067
0068 return 0;
0069 }
0070
0071 static int sunxi_ve_of_xlate(struct reset_controller_dev *rcdev,
0072 const struct of_phandle_args *reset_spec)
0073 {
0074 if (WARN_ON(reset_spec->args_count != 0))
0075 return -EINVAL;
0076
0077 return 0;
0078 }
0079
0080 static const struct reset_control_ops sunxi_ve_reset_ops = {
0081 .assert = sunxi_ve_reset_assert,
0082 .deassert = sunxi_ve_reset_deassert,
0083 };
0084
0085 static void __init sun4i_ve_clk_setup(struct device_node *node)
0086 {
0087 struct clk *clk;
0088 struct clk_divider *div;
0089 struct clk_gate *gate;
0090 struct ve_reset_data *reset_data;
0091 const char *parent;
0092 const char *clk_name = node->name;
0093 void __iomem *reg;
0094 int err;
0095
0096 reg = of_io_request_and_map(node, 0, of_node_full_name(node));
0097 if (IS_ERR(reg))
0098 return;
0099
0100 div = kzalloc(sizeof(*div), GFP_KERNEL);
0101 if (!div)
0102 goto err_unmap;
0103
0104 gate = kzalloc(sizeof(*gate), GFP_KERNEL);
0105 if (!gate)
0106 goto err_free_div;
0107
0108 of_property_read_string(node, "clock-output-names", &clk_name);
0109 parent = of_clk_get_parent_name(node, 0);
0110
0111 gate->reg = reg;
0112 gate->bit_idx = SUN4I_VE_ENABLE;
0113 gate->lock = &ve_lock;
0114
0115 div->reg = reg;
0116 div->shift = SUN4I_VE_DIVIDER_SHIFT;
0117 div->width = SUN4I_VE_DIVIDER_WIDTH;
0118 div->lock = &ve_lock;
0119
0120 clk = clk_register_composite(NULL, clk_name, &parent, 1,
0121 NULL, NULL,
0122 &div->hw, &clk_divider_ops,
0123 &gate->hw, &clk_gate_ops,
0124 CLK_SET_RATE_PARENT);
0125 if (IS_ERR(clk))
0126 goto err_free_gate;
0127
0128 err = of_clk_add_provider(node, of_clk_src_simple_get, clk);
0129 if (err)
0130 goto err_unregister_clk;
0131
0132 reset_data = kzalloc(sizeof(*reset_data), GFP_KERNEL);
0133 if (!reset_data)
0134 goto err_del_provider;
0135
0136 reset_data->reg = reg;
0137 reset_data->lock = &ve_lock;
0138 reset_data->rcdev.nr_resets = 1;
0139 reset_data->rcdev.ops = &sunxi_ve_reset_ops;
0140 reset_data->rcdev.of_node = node;
0141 reset_data->rcdev.of_xlate = sunxi_ve_of_xlate;
0142 reset_data->rcdev.of_reset_n_cells = 0;
0143 err = reset_controller_register(&reset_data->rcdev);
0144 if (err)
0145 goto err_free_reset;
0146
0147 return;
0148
0149 err_free_reset:
0150 kfree(reset_data);
0151 err_del_provider:
0152 of_clk_del_provider(node);
0153 err_unregister_clk:
0154 clk_unregister(clk);
0155 err_free_gate:
0156 kfree(gate);
0157 err_free_div:
0158 kfree(div);
0159 err_unmap:
0160 iounmap(reg);
0161 }
0162 CLK_OF_DECLARE(sun4i_ve, "allwinner,sun4i-a10-ve-clk",
0163 sun4i_ve_clk_setup);