Commit b9e3b72d authored by Linus Walleij's avatar Linus Walleij

Merge tag 'pinctrl-mergebase-20120418' into HEAD

Conflicts:
	drivers/pinctrl/core.c
parents c0af14d3 dcb5dbc3
NVIDIA Tegra20 pinmux controller
Required properties:
- compatible: "nvidia,tegra20-pinmux"
- reg: Should contain the register physical address and length for each of
the tri-state, mux, pull-up/down, and pad control register sets.
Please refer to pinctrl-bindings.txt in this directory for details of the
common pinctrl bindings used by client devices, including the meaning of the
phrase "pin configuration node".
Tegra's pin configuration nodes act as a container for an abitrary number of
subnodes. Each of these subnodes represents some desired configuration for a
pin, a group, or a list of pins or groups. This configuration can include the
mux function to select on those pin(s)/group(s), and various pin configuration
parameters, such as pull-up, tristate, drive strength, etc.
The name of each subnode is not important; all subnodes should be enumerated
and processed purely based on their content.
Each subnode only affects those parameters that are explicitly listed. In
other words, a subnode that lists a mux function but no pin configuration
parameters implies no information about any pin configuration parameters.
Similarly, a pin subnode that describes a pullup parameter implies no
information about e.g. the mux function or tristate parameter. For this
reason, even seemingly boolean values are actually tristates in this binding:
unspecified, off, or on. Unspecified is represented as an absent property,
and off/on are represented as integer values 0 and 1.
Required subnode-properties:
- nvidia,pins : An array of strings. Each string contains the name of a pin or
group. Valid values for these names are listed below.
Optional subnode-properties:
- nvidia,function: A string containing the name of the function to mux to the
pin or group. Valid values for function names are listed below. See the Tegra
TRM to determine which are valid for each pin or group.
- nvidia,pull: Integer, representing the pull-down/up to apply to the pin.
0: none, 1: down, 2: up.
- nvidia,tristate: Integer.
0: drive, 1: tristate.
- nvidia,high-speed-mode: Integer. Enable high speed mode the pins.
0: no, 1: yes.
- nvidia,schmitt: Integer. Enables Schmitt Trigger on the input.
0: no, 1: yes.
- nvidia,low-power-mode: Integer. Valid values 0-3. 0 is least power, 3 is
most power. Controls the drive power or current. See "Low Power Mode"
or "LPMD1" and "LPMD0" in the Tegra TRM.
- nvidia,pull-down-strength: Integer. Controls drive strength. 0 is weakest.
The range of valid values depends on the pingroup. See "CAL_DRVDN" in the
Tegra TRM.
- nvidia,pull-up-strength: Integer. Controls drive strength. 0 is weakest.
The range of valid values depends on the pingroup. See "CAL_DRVUP" in the
Tegra TRM.
- nvidia,slew-rate-rising: Integer. Controls rising signal slew rate. 0 is
fastest. The range of valid values depends on the pingroup. See
"DRVDN_SLWR" in the Tegra TRM.
- nvidia,slew-rate-falling: Integer. Controls falling signal slew rate. 0 is
fastest. The range of valid values depends on the pingroup. See
"DRVUP_SLWF" in the Tegra TRM.
Note that many of these properties are only valid for certain specific pins
or groups. See the Tegra TRM and various pinmux spreadsheets for complete
details regarding which groups support which functionality. The Linux pinctrl
driver may also be a useful reference, since it consolidates, disambiguates,
and corrects data from all those sources.
Valid values for pin and group names are:
mux groups:
These all support nvidia,function, nvidia,tristate, and many support
nvidia,pull.
ata, atb, atc, atd, ate, cdev1, cdev2, crtp, csus, dap1, dap2, dap3, dap4,
ddc, dta, dtb, dtc, dtd, dte, dtf, gma, gmb, gmc, gmd, gme, gpu, gpu7,
gpv, hdint, i2cp, irrx, irtx, kbca, kbcb, kbcc, kbcd, kbce, kbcf, lcsn,
ld0, ld1, ld2, ld3, ld4, ld5, ld6, ld7, ld8, ld9, ld10, ld11, ld12, ld13,
ld14, ld15, ld16, ld17, ldc, ldi, lhp0, lhp1, lhp2, lhs, lm0, lm1, lpp,
lpw0, lpw1, lpw2, lsc0, lsc1, lsck, lsda, lsdi, lspi, lvp0, lvp1, lvs,
owc, pmc, pta, rm, sdb, sdc, sdd, sdio1, slxa, slxc, slxd, slxk, spdi,
spdo, spia, spib, spic, spid, spie, spif, spig, spih, uaa, uab, uac, uad,
uca, ucb, uda.
tristate groups:
These only support nvidia,pull.
ck32, ddrc, pmca, pmcb, pmcc, pmcd, pmce, xm2c, xm2d, ls, lc, ld17_0,
ld19_18, ld21_20, ld23_22.
drive groups:
With some exceptions, these support nvidia,high-speed-mode,
nvidia,schmitt, nvidia,low-power-mode, nvidia,pull-down-strength,
nvidia,pull-up-strength, nvidia,slew_rate-rising, nvidia,slew_rate-falling.
drive_ao1, drive_ao2, drive_at1, drive_at2, drive_cdev1, drive_cdev2,
drive_csus, drive_dap1, drive_dap2, drive_dap3, drive_dap4, drive_dbg,
drive_lcd1, drive_lcd2, drive_sdmmc2, drive_sdmmc3, drive_spi, drive_uaa,
drive_uab, drive_uart2, drive_uart3, drive_vi1, drive_vi2, drive_xm2a,
drive_xm2c, drive_xm2d, drive_xm2clk, drive_sdio1, drive_crt, drive_ddc,
drive_gma, drive_gmb, drive_gmc, drive_gmd, drive_gme, drive_owr,
drive_uda.
Example:
pinctrl@70000000 {
compatible = "nvidia,tegra20-pinmux";
reg = < 0x70000014 0x10 /* Tri-state registers */
0x70000080 0x20 /* Mux registers */
0x700000a0 0x14 /* Pull-up/down registers */
0x70000868 0xa8 >; /* Pad control registers */
};
Example board file extract:
pinctrl@70000000 {
sdio4_default: sdio4_default {
atb {
nvidia,pins = "atb", "gma", "gme";
nvidia,function = "sdio4";
nvidia,pull = <0>;
nvidia,tristate = <0>;
};
};
};
sdhci@c8000600 {
pinctrl-names = "default";
pinctrl-0 = <&sdio4_default>;
};
NVIDIA Tegra30 pinmux controller
The Tegra30 pinctrl binding is very similar to the Tegra20 pinctrl binding,
as described in nvidia,tegra20-pinmux.txt. In fact, this document assumes
that binding as a baseline, and only documents the differences between the
two bindings.
Required properties:
- compatible: "nvidia,tegra30-pinmux"
- reg: Should contain the register physical address and length for each of
the pad control and mux registers.
Tegra30 adds the following optional properties for pin configuration subnodes:
- nvidia,enable-input: Integer. Enable the pin's input path. 0: no, 1: yes.
- nvidia,open-drain: Integer. Enable open drain mode. 0: no, 1: yes.
- nvidia,lock: Integer. Lock the pin configuration against further changes
until reset. 0: no, 1: yes.
- nvidia,io-reset: Integer. Reset the IO path. 0: no, 1: yes.
As with Tegra20, see the Tegra TRM for complete details regarding which groups
support which functionality.
Valid values for pin and group names are:
per-pin mux groups:
These all support nvidia,function, nvidia,tristate, nvidia,pull,
nvidia,enable-input, nvidia,lock. Some support nvidia,open-drain,
nvidia,io-reset.
clk_32k_out_pa0, uart3_cts_n_pa1, dap2_fs_pa2, dap2_sclk_pa3,
dap2_din_pa4, dap2_dout_pa5, sdmmc3_clk_pa6, sdmmc3_cmd_pa7, gmi_a17_pb0,
gmi_a18_pb1, lcd_pwr0_pb2, lcd_pclk_pb3, sdmmc3_dat3_pb4, sdmmc3_dat2_pb5,
sdmmc3_dat1_pb6, sdmmc3_dat0_pb7, uart3_rts_n_pc0, lcd_pwr1_pc1,
uart2_txd_pc2, uart2_rxd_pc3, gen1_i2c_scl_pc4, gen1_i2c_sda_pc5,
lcd_pwr2_pc6, gmi_wp_n_pc7, sdmmc3_dat5_pd0, sdmmc3_dat4_pd1, lcd_dc1_pd2,
sdmmc3_dat6_pd3, sdmmc3_dat7_pd4, vi_d1_pd5, vi_vsync_pd6, vi_hsync_pd7,
lcd_d0_pe0, lcd_d1_pe1, lcd_d2_pe2, lcd_d3_pe3, lcd_d4_pe4, lcd_d5_pe5,
lcd_d6_pe6, lcd_d7_pe7, lcd_d8_pf0, lcd_d9_pf1, lcd_d10_pf2, lcd_d11_pf3,
lcd_d12_pf4, lcd_d13_pf5, lcd_d14_pf6, lcd_d15_pf7, gmi_ad0_pg0,
gmi_ad1_pg1, gmi_ad2_pg2, gmi_ad3_pg3, gmi_ad4_pg4, gmi_ad5_pg5,
gmi_ad6_pg6, gmi_ad7_pg7, gmi_ad8_ph0, gmi_ad9_ph1, gmi_ad10_ph2,
gmi_ad11_ph3, gmi_ad12_ph4, gmi_ad13_ph5, gmi_ad14_ph6, gmi_ad15_ph7,
gmi_wr_n_pi0, gmi_oe_n_pi1, gmi_dqs_pi2, gmi_cs6_n_pi3, gmi_rst_n_pi4,
gmi_iordy_pi5, gmi_cs7_n_pi6, gmi_wait_pi7, gmi_cs0_n_pj0, lcd_de_pj1,
gmi_cs1_n_pj2, lcd_hsync_pj3, lcd_vsync_pj4, uart2_cts_n_pj5,
uart2_rts_n_pj6, gmi_a16_pj7, gmi_adv_n_pk0, gmi_clk_pk1, gmi_cs4_n_pk2,
gmi_cs2_n_pk3, gmi_cs3_n_pk4, spdif_out_pk5, spdif_in_pk6, gmi_a19_pk7,
vi_d2_pl0, vi_d3_pl1, vi_d4_pl2, vi_d5_pl3, vi_d6_pl4, vi_d7_pl5,
vi_d8_pl6, vi_d9_pl7, lcd_d16_pm0, lcd_d17_pm1, lcd_d18_pm2, lcd_d19_pm3,
lcd_d20_pm4, lcd_d21_pm5, lcd_d22_pm6, lcd_d23_pm7, dap1_fs_pn0,
dap1_din_pn1, dap1_dout_pn2, dap1_sclk_pn3, lcd_cs0_n_pn4, lcd_sdout_pn5,
lcd_dc0_pn6, hdmi_int_pn7, ulpi_data7_po0, ulpi_data0_po1, ulpi_data1_po2,
ulpi_data2_po3, ulpi_data3_po4, ulpi_data4_po5, ulpi_data5_po6,
ulpi_data6_po7, dap3_fs_pp0, dap3_din_pp1, dap3_dout_pp2, dap3_sclk_pp3,
dap4_fs_pp4, dap4_din_pp5, dap4_dout_pp6, dap4_sclk_pp7, kb_col0_pq0,
kb_col1_pq1, kb_col2_pq2, kb_col3_pq3, kb_col4_pq4, kb_col5_pq5,
kb_col6_pq6, kb_col7_pq7, kb_row0_pr0, kb_row1_pr1, kb_row2_pr2,
kb_row3_pr3, kb_row4_pr4, kb_row5_pr5, kb_row6_pr6, kb_row7_pr7,
kb_row8_ps0, kb_row9_ps1, kb_row10_ps2, kb_row11_ps3, kb_row12_ps4,
kb_row13_ps5, kb_row14_ps6, kb_row15_ps7, vi_pclk_pt0, vi_mclk_pt1,
vi_d10_pt2, vi_d11_pt3, vi_d0_pt4, gen2_i2c_scl_pt5, gen2_i2c_sda_pt6,
sdmmc4_cmd_pt7, pu0, pu1, pu2, pu3, pu4, pu5, pu6, jtag_rtck_pu7, pv0,
pv1, pv2, pv3, ddc_scl_pv4, ddc_sda_pv5, crt_hsync_pv6, crt_vsync_pv7,
lcd_cs1_n_pw0, lcd_m1_pw1, spi2_cs1_n_pw2, spi2_cs2_n_pw3, clk1_out_pw4,
clk2_out_pw5, uart3_txd_pw6, uart3_rxd_pw7, spi2_mosi_px0, spi2_miso_px1,
spi2_sck_px2, spi2_cs0_n_px3, spi1_mosi_px4, spi1_sck_px5, spi1_cs0_n_px6,
spi1_miso_px7, ulpi_clk_py0, ulpi_dir_py1, ulpi_nxt_py2, ulpi_stp_py3,
sdmmc1_dat3_py4, sdmmc1_dat2_py5, sdmmc1_dat1_py6, sdmmc1_dat0_py7,
sdmmc1_clk_pz0, sdmmc1_cmd_pz1, lcd_sdin_pz2, lcd_wr_n_pz3, lcd_sck_pz4,
sys_clk_req_pz5, pwr_i2c_scl_pz6, pwr_i2c_sda_pz7, sdmmc4_dat0_paa0,
sdmmc4_dat1_paa1, sdmmc4_dat2_paa2, sdmmc4_dat3_paa3, sdmmc4_dat4_paa4,
sdmmc4_dat5_paa5, sdmmc4_dat6_paa6, sdmmc4_dat7_paa7, pbb0,
cam_i2c_scl_pbb1, cam_i2c_sda_pbb2, pbb3, pbb4, pbb5, pbb6, pbb7,
cam_mclk_pcc0, pcc1, pcc2, sdmmc4_rst_n_pcc3, sdmmc4_clk_pcc4,
clk2_req_pcc5, pex_l2_rst_n_pcc6, pex_l2_clkreq_n_pcc7,
pex_l0_prsnt_n_pdd0, pex_l0_rst_n_pdd1, pex_l0_clkreq_n_pdd2,
pex_wake_n_pdd3, pex_l1_prsnt_n_pdd4, pex_l1_rst_n_pdd5,
pex_l1_clkreq_n_pdd6, pex_l2_prsnt_n_pdd7, clk3_out_pee0, clk3_req_pee1,
clk1_req_pee2, hdmi_cec_pee3, clk_32k_in, core_pwr_req, cpu_pwr_req, owr,
pwr_int_n.
drive groups:
These all support nvidia,pull-down-strength, nvidia,pull-up-strength,
nvidia,slew_rate-rising, nvidia,slew_rate-falling. Most but not all
support nvidia,high-speed-mode, nvidia,schmitt, nvidia,low-power-mode.
ao1, ao2, at1, at2, at3, at4, at5, cdev1, cdev2, cec, crt, csus, dap1,
dap2, dap3, dap4, dbg, ddc, dev3, gma, gmb, gmc, gmd, gme, gmf, gmg,
gmh, gpv, lcd1, lcd2, owr, sdio1, sdio2, sdio3, spi, uaa, uab, uart2,
uart3, uda, vi1.
Example:
pinctrl@70000000 {
compatible = "nvidia,tegra30-pinmux";
reg = < 0x70000868 0xd0 /* Pad control registers */
0x70003000 0x3e0 >; /* Mux registers */
};
Example board file extract:
pinctrl@70000000 {
sdmmc4_default: pinmux {
sdmmc4_clk_pcc4 {
nvidia,pins = "sdmmc4_clk_pcc4",
"sdmmc4_rst_n_pcc3";
nvidia,function = "sdmmc4";
nvidia,pull = <0>;
nvidia,tristate = <0>;
};
sdmmc4_dat0_paa0 {
nvidia,pins = "sdmmc4_dat0_paa0",
"sdmmc4_dat1_paa1",
"sdmmc4_dat2_paa2",
"sdmmc4_dat3_paa3",
"sdmmc4_dat4_paa4",
"sdmmc4_dat5_paa5",
"sdmmc4_dat6_paa6",
"sdmmc4_dat7_paa7";
nvidia,function = "sdmmc4";
nvidia,pull = <2>;
nvidia,tristate = <0>;
};
};
};
sdhci@78000400 {
pinctrl-names = "default";
pinctrl-0 = <&sdmmc4_default>;
};
== Introduction ==
Hardware modules that control pin multiplexing or configuration parameters
such as pull-up/down, tri-state, drive-strength etc are designated as pin
controllers. Each pin controller must be represented as a node in device tree,
just like any other hardware module.
Hardware modules whose signals are affected by pin configuration are
designated client devices. Again, each client device must be represented as a
node in device tree, just like any other hardware module.
For a client device to operate correctly, certain pin controllers must
set up certain specific pin configurations. Some client devices need a
single static pin configuration, e.g. set up during initialization. Others
need to reconfigure pins at run-time, for example to tri-state pins when the
device is inactive. Hence, each client device can define a set of named
states. The number and names of those states is defined by the client device's
own binding.
The common pinctrl bindings defined in this file provide an infrastructure
for client device device tree nodes to map those state names to the pin
configuration used by those states.
Note that pin controllers themselves may also be client devices of themselves.
For example, a pin controller may set up its own "active" state when the
driver loads. This would allow representing a board's static pin configuration
in a single place, rather than splitting it across multiple client device
nodes. The decision to do this or not somewhat rests with the author of
individual board device tree files, and any requirements imposed by the
bindings for the individual client devices in use by that board, i.e. whether
they require certain specific named states for dynamic pin configuration.
== Pinctrl client devices ==
For each client device individually, every pin state is assigned an integer
ID. These numbers start at 0, and are contiguous. For each state ID, a unique
property exists to define the pin configuration. Each state may also be
assigned a name. When names are used, another property exists to map from
those names to the integer IDs.
Each client device's own binding determines the set of states the must be
defined in its device tree node, and whether to define the set of state
IDs that must be provided, or whether to define the set of state names that
must be provided.
Required properties:
pinctrl-0: List of phandles, each pointing at a pin configuration
node. These referenced pin configuration nodes must be child
nodes of the pin controller that they configure. Multiple
entries may exist in this list so that multiple pin
controllers may be configured, or so that a state may be built
from multiple nodes for a single pin controller, each
contributing part of the overall configuration. See the next
section of this document for details of the format of these
pin configuration nodes.
In some cases, it may be useful to define a state, but for it
to be empty. This may be required when a common IP block is
used in an SoC either without a pin controller, or where the
pin controller does not affect the HW module in question. If
the binding for that IP block requires certain pin states to
exist, they must still be defined, but may be left empty.
Optional properties:
pinctrl-1: List of phandles, each pointing at a pin configuration
node within a pin controller.
...
pinctrl-n: List of phandles, each pointing at a pin configuration
node within a pin controller.
pinctrl-names: The list of names to assign states. List entry 0 defines the
name for integer state ID 0, list entry 1 for state ID 1, and
so on.
For example:
/* For a client device requiring named states */
device {
pinctrl-names = "active", "idle";
pinctrl-0 = <&state_0_node_a>;
pinctrl-1 = <&state_1_node_a &state_1_node_b>;
};
/* For the same device if using state IDs */
device {
pinctrl-0 = <&state_0_node_a>;
pinctrl-1 = <&state_1_node_a &state_1_node_b>;
};
/*
* For an IP block whose binding supports pin configuration,
* but in use on an SoC that doesn't have any pin control hardware
*/
device {
pinctrl-names = "active", "idle";
pinctrl-0 = <>;
pinctrl-1 = <>;
};
== Pin controller devices ==
Pin controller devices should contain the pin configuration nodes that client
devices reference.
For example:
pincontroller {
... /* Standard DT properties for the device itself elided */
state_0_node_a {
...
};
state_1_node_a {
...
};
state_1_node_b {
...
};
}
The contents of each of those pin configuration child nodes is defined
entirely by the binding for the individual pin controller device. There
exists no common standard for this content.
The pin configuration nodes need not be direct children of the pin controller
device; they may be grandchildren, for example. Whether this is legal, and
whether there is any interaction between the child and intermediate parent
nodes, is again defined entirely by the binding for the individual pin
controller device.
NVIDIA Tegra 2 pinmux controller
Required properties:
- compatible : "nvidia,tegra20-pinmux"
...@@ -276,3 +276,7 @@ REGULATOR ...@@ -276,3 +276,7 @@ REGULATOR
devm_regulator_get() devm_regulator_get()
devm_regulator_put() devm_regulator_put()
devm_regulator_bulk_get() devm_regulator_bulk_get()
PINCTRL
devm_pinctrl_get()
devm_pinctrl_put()
...@@ -152,11 +152,9 @@ static const struct foo_group foo_groups[] = { ...@@ -152,11 +152,9 @@ static const struct foo_group foo_groups[] = {
}; };
static int foo_list_groups(struct pinctrl_dev *pctldev, unsigned selector) static int foo_get_groups_count(struct pinctrl_dev *pctldev)
{ {
if (selector >= ARRAY_SIZE(foo_groups)) return ARRAY_SIZE(foo_groups);
return -EINVAL;
return 0;
} }
static const char *foo_get_group_name(struct pinctrl_dev *pctldev, static const char *foo_get_group_name(struct pinctrl_dev *pctldev,
...@@ -175,7 +173,7 @@ static int foo_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector, ...@@ -175,7 +173,7 @@ static int foo_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector,
} }
static struct pinctrl_ops foo_pctrl_ops = { static struct pinctrl_ops foo_pctrl_ops = {
.list_groups = foo_list_groups, .get_groups_count = foo_get_groups_count,
.get_group_name = foo_get_group_name, .get_group_name = foo_get_group_name,
.get_group_pins = foo_get_group_pins, .get_group_pins = foo_get_group_pins,
}; };
...@@ -186,13 +184,12 @@ static struct pinctrl_desc foo_desc = { ...@@ -186,13 +184,12 @@ static struct pinctrl_desc foo_desc = {
.pctlops = &foo_pctrl_ops, .pctlops = &foo_pctrl_ops,
}; };
The pin control subsystem will call the .list_groups() function repeatedly The pin control subsystem will call the .get_groups_count() function to
beginning on 0 until it returns non-zero to determine legal selectors, then determine total number of legal selectors, then it will call the other functions
it will call the other functions to retrieve the name and pins of the group. to retrieve the name and pins of the group. Maintaining the data structure of
Maintaining the data structure of the groups is up to the driver, this is the groups is up to the driver, this is just a simple example - in practice you
just a simple example - in practice you may need more entries in your group may need more entries in your group structure, for example specific register
structure, for example specific register ranges associated with each group ranges associated with each group and so on.
and so on.
Pin configuration Pin configuration
...@@ -606,11 +603,9 @@ static const struct foo_group foo_groups[] = { ...@@ -606,11 +603,9 @@ static const struct foo_group foo_groups[] = {
}; };
static int foo_list_groups(struct pinctrl_dev *pctldev, unsigned selector) static int foo_get_groups_count(struct pinctrl_dev *pctldev)
{ {
if (selector >= ARRAY_SIZE(foo_groups)) return ARRAY_SIZE(foo_groups);
return -EINVAL;
return 0;
} }
static const char *foo_get_group_name(struct pinctrl_dev *pctldev, static const char *foo_get_group_name(struct pinctrl_dev *pctldev,
...@@ -629,7 +624,7 @@ static int foo_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector, ...@@ -629,7 +624,7 @@ static int foo_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector,
} }
static struct pinctrl_ops foo_pctrl_ops = { static struct pinctrl_ops foo_pctrl_ops = {
.list_groups = foo_list_groups, .get_groups_count = foo_get_groups_count,
.get_group_name = foo_get_group_name, .get_group_name = foo_get_group_name,
.get_group_pins = foo_get_group_pins, .get_group_pins = foo_get_group_pins,
}; };
...@@ -640,7 +635,7 @@ struct foo_pmx_func { ...@@ -640,7 +635,7 @@ struct foo_pmx_func {
const unsigned num_groups; const unsigned num_groups;
}; };
static const char * const spi0_groups[] = { "spi0_1_grp" }; static const char * const spi0_groups[] = { "spi0_0_grp", "spi0_1_grp" };
static const char * const i2c0_groups[] = { "i2c0_grp" }; static const char * const i2c0_groups[] = { "i2c0_grp" };
static const char * const mmc0_groups[] = { "mmc0_1_grp", "mmc0_2_grp", static const char * const mmc0_groups[] = { "mmc0_1_grp", "mmc0_2_grp",
"mmc0_3_grp" }; "mmc0_3_grp" };
...@@ -663,11 +658,9 @@ static const struct foo_pmx_func foo_functions[] = { ...@@ -663,11 +658,9 @@ static const struct foo_pmx_func foo_functions[] = {
}, },
}; };
int foo_list_funcs(struct pinctrl_dev *pctldev, unsigned selector) int foo_get_functions_count(struct pinctrl_dev *pctldev)
{ {
if (selector >= ARRAY_SIZE(foo_functions)) return ARRAY_SIZE(foo_functions);
return -EINVAL;
return 0;
} }
const char *foo_get_fname(struct pinctrl_dev *pctldev, unsigned selector) const char *foo_get_fname(struct pinctrl_dev *pctldev, unsigned selector)
...@@ -703,7 +696,7 @@ void foo_disable(struct pinctrl_dev *pctldev, unsigned selector, ...@@ -703,7 +696,7 @@ void foo_disable(struct pinctrl_dev *pctldev, unsigned selector,
} }
struct pinmux_ops foo_pmxops = { struct pinmux_ops foo_pmxops = {
.list_functions = foo_list_funcs, .get_functions_count = foo_get_functions_count,
.get_function_name = foo_get_fname, .get_function_name = foo_get_fname,
.get_function_groups = foo_get_groups, .get_function_groups = foo_get_groups,
.enable = foo_enable, .enable = foo_enable,
...@@ -786,7 +779,7 @@ and spi on the second function mapping: ...@@ -786,7 +779,7 @@ and spi on the second function mapping:
#include <linux/pinctrl/machine.h> #include <linux/pinctrl/machine.h>
static const struct pinctrl_map __initdata mapping[] = { static const struct pinctrl_map mapping[] __initconst = {
{ {
.dev_name = "foo-spi.0", .dev_name = "foo-spi.0",
.name = PINCTRL_STATE_DEFAULT, .name = PINCTRL_STATE_DEFAULT,
...@@ -952,13 +945,13 @@ case), we define a mapping like this: ...@@ -952,13 +945,13 @@ case), we define a mapping like this:
The result of grabbing this mapping from the device with something like The result of grabbing this mapping from the device with something like
this (see next paragraph): this (see next paragraph):
p = pinctrl_get(dev); p = devm_pinctrl_get(dev);
s = pinctrl_lookup_state(p, "8bit"); s = pinctrl_lookup_state(p, "8bit");
ret = pinctrl_select_state(p, s); ret = pinctrl_select_state(p, s);
or more simply: or more simply:
p = pinctrl_get_select(dev, "8bit"); p = devm_pinctrl_get_select(dev, "8bit");
Will be that you activate all the three bottom records in the mapping at Will be that you activate all the three bottom records in the mapping at
once. Since they share the same name, pin controller device, function and once. Since they share the same name, pin controller device, function and
...@@ -992,7 +985,7 @@ foo_probe() ...@@ -992,7 +985,7 @@ foo_probe()
/* Allocate a state holder named "foo" etc */ /* Allocate a state holder named "foo" etc */
struct foo_state *foo = ...; struct foo_state *foo = ...;
foo->p = pinctrl_get(&device); foo->p = devm_pinctrl_get(&device);
if (IS_ERR(foo->p)) { if (IS_ERR(foo->p)) {
/* FIXME: clean up "foo" here */ /* FIXME: clean up "foo" here */
return PTR_ERR(foo->p); return PTR_ERR(foo->p);
...@@ -1000,24 +993,17 @@ foo_probe() ...@@ -1000,24 +993,17 @@ foo_probe()
foo->s = pinctrl_lookup_state(foo->p, PINCTRL_STATE_DEFAULT); foo->s = pinctrl_lookup_state(foo->p, PINCTRL_STATE_DEFAULT);
if (IS_ERR(foo->s)) { if (IS_ERR(foo->s)) {
pinctrl_put(foo->p);
/* FIXME: clean up "foo" here */ /* FIXME: clean up "foo" here */
return PTR_ERR(s); return PTR_ERR(s);
} }
ret = pinctrl_select_state(foo->s); ret = pinctrl_select_state(foo->s);
if (ret < 0) { if (ret < 0) {
pinctrl_put(foo->p);
/* FIXME: clean up "foo" here */ /* FIXME: clean up "foo" here */
return ret; return ret;
} }
} }
foo_remove()
{
pinctrl_put(state->p);
}
This get/lookup/select/put sequence can just as well be handled by bus drivers This get/lookup/select/put sequence can just as well be handled by bus drivers
if you don't want each and every driver to handle it and you know the if you don't want each and every driver to handle it and you know the
arrangement on your bus. arrangement on your bus.
...@@ -1029,6 +1015,11 @@ The semantics of the pinctrl APIs are: ...@@ -1029,6 +1015,11 @@ The semantics of the pinctrl APIs are:
kernel memory to hold the pinmux state. All mapping table parsing or similar kernel memory to hold the pinmux state. All mapping table parsing or similar
slow operations take place within this API. slow operations take place within this API.
- devm_pinctrl_get() is a variant of pinctrl_get() that causes pinctrl_put()
to be called automatically on the retrieved pointer when the associated
device is removed. It is recommended to use this function over plain
pinctrl_get().
- pinctrl_lookup_state() is called in process context to obtain a handle to a - pinctrl_lookup_state() is called in process context to obtain a handle to a
specific state for a the client device. This operation may be slow too. specific state for a the client device. This operation may be slow too.
...@@ -1041,14 +1032,30 @@ The semantics of the pinctrl APIs are: ...@@ -1041,14 +1032,30 @@ The semantics of the pinctrl APIs are:
- pinctrl_put() frees all information associated with a pinctrl handle. - pinctrl_put() frees all information associated with a pinctrl handle.
- devm_pinctrl_put() is a variant of pinctrl_put() that may be used to
explicitly destroy a pinctrl object returned by devm_pinctrl_get().
However, use of this function will be rare, due to the automatic cleanup
that will occur even without calling it.
pinctrl_get() must be paired with a plain pinctrl_put().
pinctrl_get() may not be paired with devm_pinctrl_put().
devm_pinctrl_get() can optionally be paired with devm_pinctrl_put().
devm_pinctrl_get() may not be paired with plain pinctrl_put().
Usually the pin control core handled the get/put pair and call out to the Usually the pin control core handled the get/put pair and call out to the
device drivers bookkeeping operations, like checking available functions and device drivers bookkeeping operations, like checking available functions and
the associated pins, whereas the enable/disable pass on to the pin controller the associated pins, whereas the enable/disable pass on to the pin controller
driver which takes care of activating and/or deactivating the mux setting by driver which takes care of activating and/or deactivating the mux setting by
quickly poking some registers. quickly poking some registers.
The pins are allocated for your device when you issue the pinctrl_get() call, The pins are allocated for your device when you issue the devm_pinctrl_get()
after this you should be able to see this in the debugfs listing of all pins. call, after this you should be able to see this in the debugfs listing of all
pins.
NOTE: the pinctrl system will return -EPROBE_DEFER if it cannot find the
requested pinctrl handles, for example if the pinctrl driver has not yet
registered. Thus make sure that the error path in your driver gracefully
cleans up and is ready to retry the probing later in the startup process.
System pin control hogging System pin control hogging
...@@ -1094,13 +1101,13 @@ it, disables and releases it, and muxes it in on the pins defined by group B: ...@@ -1094,13 +1101,13 @@ it, disables and releases it, and muxes it in on the pins defined by group B:
#include <linux/pinctrl/consumer.h> #include <linux/pinctrl/consumer.h>
foo_switch() struct pinctrl *p;
{ struct pinctrl_state *s1, *s2;
struct pinctrl *p;
struct pinctrl_state *s1, *s2;
foo_probe()
{
/* Setup */ /* Setup */
p = pinctrl_get(&device); p = devm_pinctrl_get(&device);
if (IS_ERR(p)) if (IS_ERR(p))
... ...
...@@ -1111,7 +1118,10 @@ foo_switch() ...@@ -1111,7 +1118,10 @@ foo_switch()
s2 = pinctrl_lookup_state(foo->p, "pos-B"); s2 = pinctrl_lookup_state(foo->p, "pos-B");
if (IS_ERR(s2)) if (IS_ERR(s2))
... ...
}
foo_switch()
{
/* Enable on position A */ /* Enable on position A */
ret = pinctrl_select_state(s1); ret = pinctrl_select_state(s1);
if (ret < 0) if (ret < 0)
...@@ -1125,8 +1135,6 @@ foo_switch() ...@@ -1125,8 +1135,6 @@ foo_switch()
... ...
... ...
pinctrl_put(p);
} }
The above has to be done from process context. The above has to be done from process context.
...@@ -1260,3 +1260,44 @@ int of_alias_get_id(struct device_node *np, const char *stem) ...@@ -1260,3 +1260,44 @@ int of_alias_get_id(struct device_node *np, const char *stem)
return id; return id;
} }
EXPORT_SYMBOL_GPL(of_alias_get_id); EXPORT_SYMBOL_GPL(of_alias_get_id);
const __be32 *of_prop_next_u32(struct property *prop, const __be32 *cur,
u32 *pu)
{
const void *curv = cur;
if (!prop)
return NULL;
if (!cur) {
curv = prop->value;
goto out_val;
}
curv += sizeof(*cur);
if (curv >= prop->value + prop->length)
return NULL;
out_val:
*pu = be32_to_cpup(curv);
return curv;
}
EXPORT_SYMBOL_GPL(of_prop_next_u32);
const char *of_prop_next_string(struct property *prop, const char *cur)
{
const void *curv = cur;
if (!prop)
return NULL;
if (!cur)
return prop->value;
curv += strlen(cur) + 1;
if (curv >= prop->value + prop->length)
return NULL;
return curv;
}
EXPORT_SYMBOL_GPL(of_prop_next_string);
...@@ -4,7 +4,6 @@ ...@@ -4,7 +4,6 @@
config PINCTRL config PINCTRL
bool bool
depends on EXPERIMENTAL
if PINCTRL if PINCTRL
......
...@@ -5,6 +5,9 @@ ccflags-$(CONFIG_DEBUG_PINCTRL) += -DDEBUG ...@@ -5,6 +5,9 @@ ccflags-$(CONFIG_DEBUG_PINCTRL) += -DDEBUG
obj-$(CONFIG_PINCTRL) += core.o obj-$(CONFIG_PINCTRL) += core.o
obj-$(CONFIG_PINMUX) += pinmux.o obj-$(CONFIG_PINMUX) += pinmux.o
obj-$(CONFIG_PINCONF) += pinconf.o obj-$(CONFIG_PINCONF) += pinconf.o
ifeq ($(CONFIG_OF),y)
obj-$(CONFIG_PINCTRL) += devicetree.o
endif
obj-$(CONFIG_GENERIC_PINCONF) += pinconf-generic.o obj-$(CONFIG_GENERIC_PINCONF) += pinconf-generic.o
obj-$(CONFIG_PINCTRL_PXA3xx) += pinctrl-pxa3xx.o obj-$(CONFIG_PINCTRL_PXA3xx) += pinctrl-pxa3xx.o
obj-$(CONFIG_PINCTRL_MMP2) += pinctrl-mmp2.o obj-$(CONFIG_PINCTRL_MMP2) += pinctrl-mmp2.o
......
...@@ -23,9 +23,11 @@ ...@@ -23,9 +23,11 @@
#include <linux/sysfs.h> #include <linux/sysfs.h>
#include <linux/debugfs.h> #include <linux/debugfs.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/pinctrl/consumer.h>
#include <linux/pinctrl/pinctrl.h> #include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/machine.h> #include <linux/pinctrl/machine.h>
#include "core.h" #include "core.h"
#include "devicetree.h"
#include "pinmux.h" #include "pinmux.h"
#include "pinconf.h" #include "pinconf.h"
...@@ -45,7 +47,7 @@ struct pinctrl_maps { ...@@ -45,7 +47,7 @@ struct pinctrl_maps {
DEFINE_MUTEX(pinctrl_mutex); DEFINE_MUTEX(pinctrl_mutex);
/* Global list of pin control devices (struct pinctrl_dev) */ /* Global list of pin control devices (struct pinctrl_dev) */
static LIST_HEAD(pinctrldev_list); LIST_HEAD(pinctrldev_list);
/* List of pin controller handles (struct pinctrl) */ /* List of pin controller handles (struct pinctrl) */
static LIST_HEAD(pinctrl_list); static LIST_HEAD(pinctrl_list);
...@@ -123,6 +125,25 @@ int pin_get_from_name(struct pinctrl_dev *pctldev, const char *name) ...@@ -123,6 +125,25 @@ int pin_get_from_name(struct pinctrl_dev *pctldev, const char *name)
return -EINVAL; return -EINVAL;
} }
/**
* pin_get_name_from_id() - look up a pin name from a pin id
* @pctldev: the pin control device to lookup the pin on
* @name: the name of the pin to look up
*/
const char *pin_get_name(struct pinctrl_dev *pctldev, const unsigned pin)
{
const struct pin_desc *desc;
desc = pin_desc_get(pctldev, pin);
if (desc == NULL) {
dev_err(pctldev->dev, "failed to get pin(%d) name\n",
pin);
return NULL;
}
return desc->name;
}
/** /**
* pin_is_valid() - check if pin exists on controller * pin_is_valid() - check if pin exists on controller
* @pctldev: the pin control device to check the pin on * @pctldev: the pin control device to check the pin on
...@@ -318,9 +339,10 @@ int pinctrl_get_group_selector(struct pinctrl_dev *pctldev, ...@@ -318,9 +339,10 @@ int pinctrl_get_group_selector(struct pinctrl_dev *pctldev,
const char *pin_group) const char *pin_group)
{ {
const struct pinctrl_ops *pctlops = pctldev->desc->pctlops; const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
unsigned ngroups = pctlops->get_groups_count(pctldev);
unsigned group_selector = 0; unsigned group_selector = 0;
while (pctlops->list_groups(pctldev, group_selector) >= 0) { while (group_selector < ngroups) {
const char *gname = pctlops->get_group_name(pctldev, const char *gname = pctlops->get_group_name(pctldev,
group_selector); group_selector);
if (!strcmp(gname, pin_group)) { if (!strcmp(gname, pin_group)) {
...@@ -516,11 +538,14 @@ static int add_setting(struct pinctrl *p, struct pinctrl_map const *map) ...@@ -516,11 +538,14 @@ static int add_setting(struct pinctrl *p, struct pinctrl_map const *map)
setting->pctldev = get_pinctrl_dev_from_devname(map->ctrl_dev_name); setting->pctldev = get_pinctrl_dev_from_devname(map->ctrl_dev_name);
if (setting->pctldev == NULL) { if (setting->pctldev == NULL) {
dev_err(p->dev, "unknown pinctrl device %s in map entry", dev_info(p->dev, "unknown pinctrl device %s in map entry, deferring probe",
map->ctrl_dev_name); map->ctrl_dev_name);
kfree(setting); kfree(setting);
/* Eventually, this should trigger deferred probe */ /*
return -ENODEV; * OK let us guess that the driver is not there yet, and
* let's defer obtaining this pinctrl handle to later...
*/
return -EPROBE_DEFER;
} }
switch (map->type) { switch (map->type) {
...@@ -579,6 +604,13 @@ static struct pinctrl *create_pinctrl(struct device *dev) ...@@ -579,6 +604,13 @@ static struct pinctrl *create_pinctrl(struct device *dev)
} }
p->dev = dev; p->dev = dev;
INIT_LIST_HEAD(&p->states); INIT_LIST_HEAD(&p->states);
INIT_LIST_HEAD(&p->dt_maps);
ret = pinctrl_dt_to_map(p);
if (ret < 0) {
kfree(p);
return ERR_PTR(ret);
}
devname = dev_name(dev); devname = dev_name(dev);
...@@ -662,6 +694,8 @@ static void pinctrl_put_locked(struct pinctrl *p, bool inlist) ...@@ -662,6 +694,8 @@ static void pinctrl_put_locked(struct pinctrl *p, bool inlist)
kfree(state); kfree(state);
} }
pinctrl_dt_free_maps(p);
if (inlist) if (inlist)
list_del(&p->node); list_del(&p->node);
kfree(p); kfree(p);
...@@ -787,15 +821,63 @@ int pinctrl_select_state(struct pinctrl *p, struct pinctrl_state *state) ...@@ -787,15 +821,63 @@ int pinctrl_select_state(struct pinctrl *p, struct pinctrl_state *state)
} }
EXPORT_SYMBOL_GPL(pinctrl_select_state); EXPORT_SYMBOL_GPL(pinctrl_select_state);
static void devm_pinctrl_release(struct device *dev, void *res)
{
pinctrl_put(*(struct pinctrl **)res);
}
/** /**
* pinctrl_register_mappings() - register a set of pin controller mappings * struct devm_pinctrl_get() - Resource managed pinctrl_get()
* @maps: the pincontrol mappings table to register. This should probably be * @dev: the device to obtain the handle for
* marked with __initdata so it can be discarded after boot. This *
* function will perform a shallow copy for the mapping entries. * If there is a need to explicitly destroy the returned struct pinctrl,
* @num_maps: the number of maps in the mapping table * devm_pinctrl_put() should be used, rather than plain pinctrl_put().
*/ */
int pinctrl_register_mappings(struct pinctrl_map const *maps, struct pinctrl *devm_pinctrl_get(struct device *dev)
unsigned num_maps) {
struct pinctrl **ptr, *p;
ptr = devres_alloc(devm_pinctrl_release, sizeof(*ptr), GFP_KERNEL);
if (!ptr)
return ERR_PTR(-ENOMEM);
p = pinctrl_get(dev);
if (!IS_ERR(p)) {
*ptr = p;
devres_add(dev, ptr);
} else {
devres_free(ptr);
}
return p;
}
EXPORT_SYMBOL_GPL(devm_pinctrl_get);
static int devm_pinctrl_match(struct device *dev, void *res, void *data)
{
struct pinctrl **p = res;
return *p == data;
}
/**
* devm_pinctrl_put() - Resource managed pinctrl_put()
* @p: the pinctrl handle to release
*
* Deallocate a struct pinctrl obtained via devm_pinctrl_get(). Normally
* this function will not need to be called and the resource management
* code will ensure that the resource is freed.
*/
void devm_pinctrl_put(struct pinctrl *p)
{
WARN_ON(devres_destroy(p->dev, devm_pinctrl_release,
devm_pinctrl_match, p));
pinctrl_put(p);
}
EXPORT_SYMBOL_GPL(devm_pinctrl_put);
int pinctrl_register_map(struct pinctrl_map const *maps, unsigned num_maps,
bool dup, bool locked)
{ {
int i, ret; int i, ret;
struct pinctrl_maps *maps_node; struct pinctrl_maps *maps_node;
...@@ -851,20 +933,52 @@ int pinctrl_register_mappings(struct pinctrl_map const *maps, ...@@ -851,20 +933,52 @@ int pinctrl_register_mappings(struct pinctrl_map const *maps,
} }
maps_node->num_maps = num_maps; maps_node->num_maps = num_maps;
maps_node->maps = kmemdup(maps, sizeof(*maps) * num_maps, GFP_KERNEL); if (dup) {
if (!maps_node->maps) { maps_node->maps = kmemdup(maps, sizeof(*maps) * num_maps,
pr_err("failed to duplicate mapping table\n"); GFP_KERNEL);
kfree(maps_node); if (!maps_node->maps) {
return -ENOMEM; pr_err("failed to duplicate mapping table\n");
kfree(maps_node);
return -ENOMEM;
}
} else {
maps_node->maps = maps;
} }
mutex_lock(&pinctrl_mutex); if (!locked)
mutex_lock(&pinctrl_mutex);
list_add_tail(&maps_node->node, &pinctrl_maps); list_add_tail(&maps_node->node, &pinctrl_maps);
mutex_unlock(&pinctrl_mutex); if (!locked)
mutex_unlock(&pinctrl_mutex);
return 0; return 0;
} }
/**
* pinctrl_register_mappings() - register a set of pin controller mappings
* @maps: the pincontrol mappings table to register. This should probably be
* marked with __initdata so it can be discarded after boot. This
* function will perform a shallow copy for the mapping entries.
* @num_maps: the number of maps in the mapping table
*/
int pinctrl_register_mappings(struct pinctrl_map const *maps,
unsigned num_maps)
{
return pinctrl_register_map(maps, num_maps, true, false);
}
void pinctrl_unregister_map(struct pinctrl_map const *map)
{
struct pinctrl_maps *maps_node;
list_for_each_entry(maps_node, &pinctrl_maps, node) {
if (maps_node->maps == map) {
list_del(&maps_node->node);
return;
}
}
}
#ifdef CONFIG_DEBUG_FS #ifdef CONFIG_DEBUG_FS
static int pinctrl_pins_show(struct seq_file *s, void *what) static int pinctrl_pins_show(struct seq_file *s, void *what)
...@@ -906,15 +1020,17 @@ static int pinctrl_groups_show(struct seq_file *s, void *what) ...@@ -906,15 +1020,17 @@ static int pinctrl_groups_show(struct seq_file *s, void *what)
{ {
struct pinctrl_dev *pctldev = s->private; struct pinctrl_dev *pctldev = s->private;
const struct pinctrl_ops *ops = pctldev->desc->pctlops; const struct pinctrl_ops *ops = pctldev->desc->pctlops;
unsigned selector = 0; unsigned ngroups, selector = 0;
ngroups = ops->get_groups_count(pctldev);
mutex_lock(&pinctrl_mutex); mutex_lock(&pinctrl_mutex);
seq_puts(s, "registered pin groups:\n"); seq_puts(s, "registered pin groups:\n");
while (ops->list_groups(pctldev, selector) >= 0) { while (selector < ngroups) {
const unsigned *pins; const unsigned *pins;
unsigned num_pins; unsigned num_pins;
const char *gname = ops->get_group_name(pctldev, selector); const char *gname = ops->get_group_name(pctldev, selector);
const char *pname;
int ret; int ret;
int i; int i;
...@@ -924,10 +1040,14 @@ static int pinctrl_groups_show(struct seq_file *s, void *what) ...@@ -924,10 +1040,14 @@ static int pinctrl_groups_show(struct seq_file *s, void *what)
seq_printf(s, "%s [ERROR GETTING PINS]\n", seq_printf(s, "%s [ERROR GETTING PINS]\n",
gname); gname);
else { else {
seq_printf(s, "group: %s, pins = [ ", gname); seq_printf(s, "group: %s\n", gname);
for (i = 0; i < num_pins; i++) for (i = 0; i < num_pins; i++) {
seq_printf(s, "%d ", pins[i]); pname = pin_get_name(pctldev, pins[i]);
seq_puts(s, "]\n"); if (WARN_ON(!pname))
return -EINVAL;
seq_printf(s, "pin %d (%s)\n", pins[i], pname);
}
seq_puts(s, "\n");
} }
selector++; selector++;
} }
...@@ -1226,11 +1346,14 @@ static int pinctrl_check_ops(struct pinctrl_dev *pctldev) ...@@ -1226,11 +1346,14 @@ static int pinctrl_check_ops(struct pinctrl_dev *pctldev)
const struct pinctrl_ops *ops = pctldev->desc->pctlops; const struct pinctrl_ops *ops = pctldev->desc->pctlops;
if (!ops || if (!ops ||
!ops->list_groups || !ops->get_groups_count ||
!ops->get_group_name || !ops->get_group_name ||
!ops->get_group_pins) !ops->get_group_pins)
return -EINVAL; return -EINVAL;
if (ops->dt_node_to_map && !ops->dt_free_map)
return -EINVAL;
return 0; return 0;
} }
......
...@@ -52,12 +52,15 @@ struct pinctrl_dev { ...@@ -52,12 +52,15 @@ struct pinctrl_dev {
* @dev: the device using this pin control handle * @dev: the device using this pin control handle
* @states: a list of states for this device * @states: a list of states for this device
* @state: the current state * @state: the current state
* @dt_maps: the mapping table chunks dynamically parsed from device tree for
* this device, if any
*/ */
struct pinctrl { struct pinctrl {
struct list_head node; struct list_head node;
struct device *dev; struct device *dev;
struct list_head states; struct list_head states;
struct pinctrl_state *state; struct pinctrl_state *state;
struct list_head dt_maps;
}; };
/** /**
...@@ -100,7 +103,8 @@ struct pinctrl_setting_configs { ...@@ -100,7 +103,8 @@ struct pinctrl_setting_configs {
* struct pinctrl_setting - an individual mux or config setting * struct pinctrl_setting - an individual mux or config setting
* @node: list node for struct pinctrl_settings's @settings field * @node: list node for struct pinctrl_settings's @settings field
* @type: the type of setting * @type: the type of setting
* @pctldev: pin control device handling to be programmed * @pctldev: pin control device handling to be programmed. Not used for
* PIN_MAP_TYPE_DUMMY_STATE.
* @data: Data specific to the setting type * @data: Data specific to the setting type
*/ */
struct pinctrl_setting { struct pinctrl_setting {
...@@ -144,6 +148,7 @@ struct pin_desc { ...@@ -144,6 +148,7 @@ struct pin_desc {
struct pinctrl_dev *get_pinctrl_dev_from_devname(const char *dev_name); struct pinctrl_dev *get_pinctrl_dev_from_devname(const char *dev_name);
int pin_get_from_name(struct pinctrl_dev *pctldev, const char *name); int pin_get_from_name(struct pinctrl_dev *pctldev, const char *name);
const char *pin_get_name(struct pinctrl_dev *pctldev, const unsigned pin);
int pinctrl_get_group_selector(struct pinctrl_dev *pctldev, int pinctrl_get_group_selector(struct pinctrl_dev *pctldev,
const char *pin_group); const char *pin_group);
...@@ -153,4 +158,9 @@ static inline struct pin_desc *pin_desc_get(struct pinctrl_dev *pctldev, ...@@ -153,4 +158,9 @@ static inline struct pin_desc *pin_desc_get(struct pinctrl_dev *pctldev,
return radix_tree_lookup(&pctldev->pin_desc_tree, pin); return radix_tree_lookup(&pctldev->pin_desc_tree, pin);
} }
int pinctrl_register_map(struct pinctrl_map const *maps, unsigned num_maps,
bool dup, bool locked);
void pinctrl_unregister_map(struct pinctrl_map const *map);
extern struct mutex pinctrl_mutex; extern struct mutex pinctrl_mutex;
extern struct list_head pinctrldev_list;
/*
* Device tree integration for the pin control subsystem
*
* Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <linux/device.h>
#include <linux/of.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/slab.h>
#include "core.h"
#include "devicetree.h"
/**
* struct pinctrl_dt_map - mapping table chunk parsed from device tree
* @node: list node for struct pinctrl's @dt_maps field
* @pctldev: the pin controller that allocated this struct, and will free it
* @maps: the mapping table entries
*/
struct pinctrl_dt_map {
struct list_head node;
struct pinctrl_dev *pctldev;
struct pinctrl_map *map;
unsigned num_maps;
};
static void dt_free_map(struct pinctrl_dev *pctldev,
struct pinctrl_map *map, unsigned num_maps)
{
if (pctldev) {
struct pinctrl_ops *ops = pctldev->desc->pctlops;
ops->dt_free_map(pctldev, map, num_maps);
} else {
/* There is no pctldev for PIN_MAP_TYPE_DUMMY_STATE */
kfree(map);
}
}
void pinctrl_dt_free_maps(struct pinctrl *p)
{
struct pinctrl_dt_map *dt_map, *n1;
list_for_each_entry_safe(dt_map, n1, &p->dt_maps, node) {
pinctrl_unregister_map(dt_map->map);
list_del(&dt_map->node);
dt_free_map(dt_map->pctldev, dt_map->map,
dt_map->num_maps);
kfree(dt_map);
}
of_node_put(p->dev->of_node);
}
static int dt_remember_or_free_map(struct pinctrl *p, const char *statename,
struct pinctrl_dev *pctldev,
struct pinctrl_map *map, unsigned num_maps)
{
int i;
struct pinctrl_dt_map *dt_map;
/* Initialize common mapping table entry fields */
for (i = 0; i < num_maps; i++) {
map[i].dev_name = dev_name(p->dev);
map[i].name = statename;
if (pctldev)
map[i].ctrl_dev_name = dev_name(pctldev->dev);
}
/* Remember the converted mapping table entries */
dt_map = kzalloc(sizeof(*dt_map), GFP_KERNEL);
if (!dt_map) {
dev_err(p->dev, "failed to alloc struct pinctrl_dt_map\n");
dt_free_map(pctldev, map, num_maps);
return -ENOMEM;
}
dt_map->pctldev = pctldev;
dt_map->map = map;
dt_map->num_maps = num_maps;
list_add_tail(&dt_map->node, &p->dt_maps);
return pinctrl_register_map(map, num_maps, false, true);
}
static struct pinctrl_dev *find_pinctrl_by_of_node(struct device_node *np)
{
struct pinctrl_dev *pctldev;
list_for_each_entry(pctldev, &pinctrldev_list, node)
if (pctldev->dev->of_node == np)
return pctldev;
return NULL;
}
static int dt_to_map_one_config(struct pinctrl *p, const char *statename,
struct device_node *np_config)
{
struct device_node *np_pctldev;
struct pinctrl_dev *pctldev;
struct pinctrl_ops *ops;
int ret;
struct pinctrl_map *map;
unsigned num_maps;
/* Find the pin controller containing np_config */
np_pctldev = of_node_get(np_config);
for (;;) {
np_pctldev = of_get_next_parent(np_pctldev);
if (!np_pctldev || of_node_is_root(np_pctldev)) {
dev_info(p->dev, "could not find pctldev for node %s, deferring probe\n",
np_config->full_name);
of_node_put(np_pctldev);
/* OK let's just assume this will appear later then */
return -EPROBE_DEFER;
}
pctldev = find_pinctrl_by_of_node(np_pctldev);
if (pctldev)
break;
}
of_node_put(np_pctldev);
/*
* Call pinctrl driver to parse device tree node, and
* generate mapping table entries
*/
ops = pctldev->desc->pctlops;
if (!ops->dt_node_to_map) {
dev_err(p->dev, "pctldev %s doesn't support DT\n",
dev_name(pctldev->dev));
return -ENODEV;
}
ret = ops->dt_node_to_map(pctldev, np_config, &map, &num_maps);
if (ret < 0)
return ret;
/* Stash the mapping table chunk away for later use */
return dt_remember_or_free_map(p, statename, pctldev, map, num_maps);
}
static int dt_remember_dummy_state(struct pinctrl *p, const char *statename)
{
struct pinctrl_map *map;
map = kzalloc(sizeof(*map), GFP_KERNEL);
if (!map) {
dev_err(p->dev, "failed to alloc struct pinctrl_map\n");
return -ENOMEM;
}
/* There is no pctldev for PIN_MAP_TYPE_DUMMY_STATE */
map->type = PIN_MAP_TYPE_DUMMY_STATE;
return dt_remember_or_free_map(p, statename, NULL, map, 1);
}
int pinctrl_dt_to_map(struct pinctrl *p)
{
struct device_node *np = p->dev->of_node;
int state, ret;
char *propname;
struct property *prop;
const char *statename;
const __be32 *list;
int size, config;
phandle phandle;
struct device_node *np_config;
/* CONFIG_OF enabled, p->dev not instantiated from DT */
if (!np) {
dev_dbg(p->dev, "no of_node; not parsing pinctrl DT\n");
return 0;
}
/* We may store pointers to property names within the node */
of_node_get(np);
/* For each defined state ID */
for (state = 0; ; state++) {
/* Retrieve the pinctrl-* property */
propname = kasprintf(GFP_KERNEL, "pinctrl-%d", state);
prop = of_find_property(np, propname, &size);
kfree(propname);
if (!prop)
break;
list = prop->value;
size /= sizeof(*list);
/* Determine whether pinctrl-names property names the state */
ret = of_property_read_string_index(np, "pinctrl-names",
state, &statename);
/*
* If not, statename is just the integer state ID. But rather
* than dynamically allocate it and have to free it later,
* just point part way into the property name for the string.
*/
if (ret < 0) {
/* strlen("pinctrl-") == 8 */
statename = prop->name + 8;
}
/* For every referenced pin configuration node in it */
for (config = 0; config < size; config++) {
phandle = be32_to_cpup(list++);
/* Look up the pin configuration node */
np_config = of_find_node_by_phandle(phandle);
if (!np_config) {
dev_err(p->dev,
"prop %s index %i invalid phandle\n",
prop->name, config);
ret = -EINVAL;
goto err;
}
/* Parse the node */
ret = dt_to_map_one_config(p, statename, np_config);
of_node_put(np_config);
if (ret < 0)
goto err;
}
/* No entries in DT? Generate a dummy state table entry */
if (!size) {
ret = dt_remember_dummy_state(p, statename);
if (ret < 0)
goto err;
}
}
return 0;
err:
pinctrl_dt_free_maps(p);
return ret;
}
/*
* Internal interface to pinctrl device tree integration
*
* Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef CONFIG_OF
void pinctrl_dt_free_maps(struct pinctrl *p);
int pinctrl_dt_to_map(struct pinctrl *p);
#else
static inline int pinctrl_dt_to_map(struct pinctrl *p)
{
return 0;
}
static inline void pinctrl_dt_free_maps(struct pinctrl *p)
{
}
#endif
...@@ -379,8 +379,16 @@ int pinconf_apply_setting(struct pinctrl_setting const *setting) ...@@ -379,8 +379,16 @@ int pinconf_apply_setting(struct pinctrl_setting const *setting)
void pinconf_show_map(struct seq_file *s, struct pinctrl_map const *map) void pinconf_show_map(struct seq_file *s, struct pinctrl_map const *map)
{ {
struct pinctrl_dev *pctldev;
const struct pinconf_ops *confops;
int i; int i;
pctldev = get_pinctrl_dev_from_devname(map->ctrl_dev_name);
if (pctldev)
confops = pctldev->desc->confops;
else
confops = NULL;
switch (map->type) { switch (map->type) {
case PIN_MAP_TYPE_CONFIGS_PIN: case PIN_MAP_TYPE_CONFIGS_PIN:
seq_printf(s, "pin "); seq_printf(s, "pin ");
...@@ -394,8 +402,15 @@ void pinconf_show_map(struct seq_file *s, struct pinctrl_map const *map) ...@@ -394,8 +402,15 @@ void pinconf_show_map(struct seq_file *s, struct pinctrl_map const *map)
seq_printf(s, "%s\n", map->data.configs.group_or_pin); seq_printf(s, "%s\n", map->data.configs.group_or_pin);
for (i = 0; i < map->data.configs.num_configs; i++) for (i = 0; i < map->data.configs.num_configs; i++) {
seq_printf(s, "config %08lx\n", map->data.configs.configs[i]); seq_printf(s, "config ");
if (confops && confops->pin_config_config_dbg_show)
confops->pin_config_config_dbg_show(pctldev, s,
map->data.configs.configs[i]);
else
seq_printf(s, "%08lx", map->data.configs.configs[i]);
seq_printf(s, "\n");
}
} }
void pinconf_show_setting(struct seq_file *s, void pinconf_show_setting(struct seq_file *s,
...@@ -403,6 +418,7 @@ void pinconf_show_setting(struct seq_file *s, ...@@ -403,6 +418,7 @@ void pinconf_show_setting(struct seq_file *s,
{ {
struct pinctrl_dev *pctldev = setting->pctldev; struct pinctrl_dev *pctldev = setting->pctldev;
const struct pinctrl_ops *pctlops = pctldev->desc->pctlops; const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
const struct pinconf_ops *confops = pctldev->desc->confops;
struct pin_desc *desc; struct pin_desc *desc;
int i; int i;
...@@ -428,8 +444,15 @@ void pinconf_show_setting(struct seq_file *s, ...@@ -428,8 +444,15 @@ void pinconf_show_setting(struct seq_file *s,
* FIXME: We should really get the pin controler to dump the config * FIXME: We should really get the pin controler to dump the config
* values, so they can be decoded to something meaningful. * values, so they can be decoded to something meaningful.
*/ */
for (i = 0; i < setting->data.configs.num_configs; i++) for (i = 0; i < setting->data.configs.num_configs; i++) {
seq_printf(s, " %08lx", setting->data.configs.configs[i]); seq_printf(s, " ");
if (confops && confops->pin_config_config_dbg_show)
confops->pin_config_config_dbg_show(pctldev, s,
setting->data.configs.configs[i]);
else
seq_printf(s, "%08lx",
setting->data.configs.configs[i]);
}
seq_printf(s, "\n"); seq_printf(s, "\n");
} }
...@@ -448,10 +471,14 @@ static void pinconf_dump_pin(struct pinctrl_dev *pctldev, ...@@ -448,10 +471,14 @@ static void pinconf_dump_pin(struct pinctrl_dev *pctldev,
static int pinconf_pins_show(struct seq_file *s, void *what) static int pinconf_pins_show(struct seq_file *s, void *what)
{ {
struct pinctrl_dev *pctldev = s->private; struct pinctrl_dev *pctldev = s->private;
const struct pinconf_ops *ops = pctldev->desc->confops;
unsigned i, pin; unsigned i, pin;
if (!ops || !ops->pin_config_get)
return 0;
seq_puts(s, "Pin config settings per pin\n"); seq_puts(s, "Pin config settings per pin\n");
seq_puts(s, "Format: pin (name): pinmux setting array\n"); seq_puts(s, "Format: pin (name): configs\n");
mutex_lock(&pinctrl_mutex); mutex_lock(&pinctrl_mutex);
...@@ -495,17 +522,18 @@ static int pinconf_groups_show(struct seq_file *s, void *what) ...@@ -495,17 +522,18 @@ static int pinconf_groups_show(struct seq_file *s, void *what)
struct pinctrl_dev *pctldev = s->private; struct pinctrl_dev *pctldev = s->private;
const struct pinctrl_ops *pctlops = pctldev->desc->pctlops; const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
const struct pinconf_ops *ops = pctldev->desc->confops; const struct pinconf_ops *ops = pctldev->desc->confops;
unsigned ngroups = pctlops->get_groups_count(pctldev);
unsigned selector = 0; unsigned selector = 0;
if (!ops || !ops->pin_config_group_get) if (!ops || !ops->pin_config_group_get)
return 0; return 0;
seq_puts(s, "Pin config settings per pin group\n"); seq_puts(s, "Pin config settings per pin group\n");
seq_puts(s, "Format: group (name): pinmux setting array\n"); seq_puts(s, "Format: group (name): configs\n");
mutex_lock(&pinctrl_mutex); mutex_lock(&pinctrl_mutex);
while (pctlops->list_groups(pctldev, selector) >= 0) { while (selector < ngroups) {
const char *gname = pctlops->get_group_name(pctldev, selector); const char *gname = pctlops->get_group_name(pctldev, selector);
seq_printf(s, "%u (%s):", selector, gname); seq_printf(s, "%u (%s):", selector, gname);
......
...@@ -19,11 +19,6 @@ int pinconf_map_to_setting(struct pinctrl_map const *map, ...@@ -19,11 +19,6 @@ int pinconf_map_to_setting(struct pinctrl_map const *map,
struct pinctrl_setting *setting); struct pinctrl_setting *setting);
void pinconf_free_setting(struct pinctrl_setting const *setting); void pinconf_free_setting(struct pinctrl_setting const *setting);
int pinconf_apply_setting(struct pinctrl_setting const *setting); int pinconf_apply_setting(struct pinctrl_setting const *setting);
void pinconf_show_map(struct seq_file *s, struct pinctrl_map const *map);
void pinconf_show_setting(struct seq_file *s,
struct pinctrl_setting const *setting);
void pinconf_init_device_debugfs(struct dentry *devroot,
struct pinctrl_dev *pctldev);
/* /*
* You will only be interested in these if you're using PINCONF * You will only be interested in these if you're using PINCONF
...@@ -61,6 +56,18 @@ static inline int pinconf_apply_setting(struct pinctrl_setting const *setting) ...@@ -61,6 +56,18 @@ static inline int pinconf_apply_setting(struct pinctrl_setting const *setting)
return 0; return 0;
} }
#endif
#if defined(CONFIG_PINCONF) && defined(CONFIG_DEBUG_FS)
void pinconf_show_map(struct seq_file *s, struct pinctrl_map const *map);
void pinconf_show_setting(struct seq_file *s,
struct pinctrl_setting const *setting);
void pinconf_init_device_debugfs(struct dentry *devroot,
struct pinctrl_dev *pctldev);
#else
static inline void pinconf_show_map(struct seq_file *s, static inline void pinconf_show_map(struct seq_file *s,
struct pinctrl_map const *map) struct pinctrl_map const *map)
{ {
......
...@@ -174,7 +174,7 @@ struct u300_gpio_confdata { ...@@ -174,7 +174,7 @@ struct u300_gpio_confdata {
/* Initial configuration */ /* Initial configuration */
static const struct __initdata u300_gpio_confdata static const struct __initconst u300_gpio_confdata
bs335_gpio_config[BS335_GPIO_NUM_PORTS][U300_GPIO_PINS_PER_PORT] = { bs335_gpio_config[BS335_GPIO_NUM_PORTS][U300_GPIO_PINS_PER_PORT] = {
/* Port 0, pins 0-7 */ /* Port 0, pins 0-7 */
{ {
...@@ -255,7 +255,7 @@ bs335_gpio_config[BS335_GPIO_NUM_PORTS][U300_GPIO_PINS_PER_PORT] = { ...@@ -255,7 +255,7 @@ bs335_gpio_config[BS335_GPIO_NUM_PORTS][U300_GPIO_PINS_PER_PORT] = {
} }
}; };
static const struct __initdata u300_gpio_confdata static const struct __initconst u300_gpio_confdata
bs365_gpio_config[BS365_GPIO_NUM_PORTS][U300_GPIO_PINS_PER_PORT] = { bs365_gpio_config[BS365_GPIO_NUM_PORTS][U300_GPIO_PINS_PER_PORT] = {
/* Port 0, pins 0-7 */ /* Port 0, pins 0-7 */
{ {
......
...@@ -25,20 +25,18 @@ static struct pinctrl_gpio_range pxa3xx_pinctrl_gpio_range = { ...@@ -25,20 +25,18 @@ static struct pinctrl_gpio_range pxa3xx_pinctrl_gpio_range = {
.pin_base = 0, .pin_base = 0,
}; };
static int pxa3xx_list_groups(struct pinctrl_dev *pctrldev, unsigned selector) static int pxa3xx_get_groups_count(struct pinctrl_dev *pctrldev)
{ {
struct pxa3xx_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev); struct pxa3xx_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
if (selector >= info->num_grps)
return -EINVAL; return info->num_grps;
return 0;
} }
static const char *pxa3xx_get_group_name(struct pinctrl_dev *pctrldev, static const char *pxa3xx_get_group_name(struct pinctrl_dev *pctrldev,
unsigned selector) unsigned selector)
{ {
struct pxa3xx_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev); struct pxa3xx_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
if (selector >= info->num_grps)
return NULL;
return info->grps[selector].name; return info->grps[selector].name;
} }
...@@ -48,25 +46,23 @@ static int pxa3xx_get_group_pins(struct pinctrl_dev *pctrldev, ...@@ -48,25 +46,23 @@ static int pxa3xx_get_group_pins(struct pinctrl_dev *pctrldev,
unsigned *num_pins) unsigned *num_pins)
{ {
struct pxa3xx_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev); struct pxa3xx_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
if (selector >= info->num_grps)
return -EINVAL;
*pins = info->grps[selector].pins; *pins = info->grps[selector].pins;
*num_pins = info->grps[selector].npins; *num_pins = info->grps[selector].npins;
return 0; return 0;
} }
static struct pinctrl_ops pxa3xx_pctrl_ops = { static struct pinctrl_ops pxa3xx_pctrl_ops = {
.list_groups = pxa3xx_list_groups, .get_groups_count = pxa3xx_get_groups_count,
.get_group_name = pxa3xx_get_group_name, .get_group_name = pxa3xx_get_group_name,
.get_group_pins = pxa3xx_get_group_pins, .get_group_pins = pxa3xx_get_group_pins,
}; };
static int pxa3xx_pmx_list_func(struct pinctrl_dev *pctrldev, unsigned func) static int pxa3xx_pmx_get_funcs_count(struct pinctrl_dev *pctrldev)
{ {
struct pxa3xx_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev); struct pxa3xx_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
if (func >= info->num_funcs)
return -EINVAL; return info->num_funcs;
return 0;
} }
static const char *pxa3xx_pmx_get_func_name(struct pinctrl_dev *pctrldev, static const char *pxa3xx_pmx_get_func_name(struct pinctrl_dev *pctrldev,
...@@ -170,7 +166,7 @@ static int pxa3xx_pmx_request_gpio(struct pinctrl_dev *pctrldev, ...@@ -170,7 +166,7 @@ static int pxa3xx_pmx_request_gpio(struct pinctrl_dev *pctrldev,
} }
static struct pinmux_ops pxa3xx_pmx_ops = { static struct pinmux_ops pxa3xx_pmx_ops = {
.list_functions = pxa3xx_pmx_list_func, .get_functions_count = pxa3xx_pmx_get_funcs_count,
.get_function_name = pxa3xx_pmx_get_func_name, .get_function_name = pxa3xx_pmx_get_func_name,
.get_function_groups = pxa3xx_pmx_get_groups, .get_function_groups = pxa3xx_pmx_get_groups,
.enable = pxa3xx_pmx_enable, .enable = pxa3xx_pmx_enable,
......
...@@ -853,18 +853,14 @@ static const struct sirfsoc_pin_group sirfsoc_pin_groups[] = { ...@@ -853,18 +853,14 @@ static const struct sirfsoc_pin_group sirfsoc_pin_groups[] = {
SIRFSOC_PIN_GROUP("gpsgrp", gps_pins), SIRFSOC_PIN_GROUP("gpsgrp", gps_pins),
}; };
static int sirfsoc_list_groups(struct pinctrl_dev *pctldev, unsigned selector) static int sirfsoc_get_groups_count(struct pinctrl_dev *pctldev)
{ {
if (selector >= ARRAY_SIZE(sirfsoc_pin_groups)) return ARRAY_SIZE(sirfsoc_pin_groups);
return -EINVAL;
return 0;
} }
static const char *sirfsoc_get_group_name(struct pinctrl_dev *pctldev, static const char *sirfsoc_get_group_name(struct pinctrl_dev *pctldev,
unsigned selector) unsigned selector)
{ {
if (selector >= ARRAY_SIZE(sirfsoc_pin_groups))
return NULL;
return sirfsoc_pin_groups[selector].name; return sirfsoc_pin_groups[selector].name;
} }
...@@ -872,8 +868,6 @@ static int sirfsoc_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector ...@@ -872,8 +868,6 @@ static int sirfsoc_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector
const unsigned **pins, const unsigned **pins,
unsigned *num_pins) unsigned *num_pins)
{ {
if (selector >= ARRAY_SIZE(sirfsoc_pin_groups))
return -EINVAL;
*pins = sirfsoc_pin_groups[selector].pins; *pins = sirfsoc_pin_groups[selector].pins;
*num_pins = sirfsoc_pin_groups[selector].num_pins; *num_pins = sirfsoc_pin_groups[selector].num_pins;
return 0; return 0;
...@@ -886,7 +880,7 @@ static void sirfsoc_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s ...@@ -886,7 +880,7 @@ static void sirfsoc_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s
} }
static struct pinctrl_ops sirfsoc_pctrl_ops = { static struct pinctrl_ops sirfsoc_pctrl_ops = {
.list_groups = sirfsoc_list_groups, .get_groups_count = sirfsoc_get_groups_count,
.get_group_name = sirfsoc_get_group_name, .get_group_name = sirfsoc_get_group_name,
.get_group_pins = sirfsoc_get_group_pins, .get_group_pins = sirfsoc_get_group_pins,
.pin_dbg_show = sirfsoc_pin_dbg_show, .pin_dbg_show = sirfsoc_pin_dbg_show,
...@@ -1033,11 +1027,9 @@ static void sirfsoc_pinmux_disable(struct pinctrl_dev *pmxdev, unsigned selector ...@@ -1033,11 +1027,9 @@ static void sirfsoc_pinmux_disable(struct pinctrl_dev *pmxdev, unsigned selector
sirfsoc_pinmux_endisable(spmx, selector, false); sirfsoc_pinmux_endisable(spmx, selector, false);
} }
static int sirfsoc_pinmux_list_funcs(struct pinctrl_dev *pmxdev, unsigned selector) static int sirfsoc_pinmux_get_funcs_count(struct pinctrl_dev *pmxdev)
{ {
if (selector >= ARRAY_SIZE(sirfsoc_pmx_functions)) return ARRAY_SIZE(sirfsoc_pmx_functions);
return -EINVAL;
return 0;
} }
static const char *sirfsoc_pinmux_get_func_name(struct pinctrl_dev *pctldev, static const char *sirfsoc_pinmux_get_func_name(struct pinctrl_dev *pctldev,
...@@ -1074,9 +1066,9 @@ static int sirfsoc_pinmux_request_gpio(struct pinctrl_dev *pmxdev, ...@@ -1074,9 +1066,9 @@ static int sirfsoc_pinmux_request_gpio(struct pinctrl_dev *pmxdev,
} }
static struct pinmux_ops sirfsoc_pinmux_ops = { static struct pinmux_ops sirfsoc_pinmux_ops = {
.list_functions = sirfsoc_pinmux_list_funcs,
.enable = sirfsoc_pinmux_enable, .enable = sirfsoc_pinmux_enable,
.disable = sirfsoc_pinmux_disable, .disable = sirfsoc_pinmux_disable,
.get_functions_count = sirfsoc_pinmux_get_funcs_count,
.get_function_name = sirfsoc_pinmux_get_func_name, .get_function_name = sirfsoc_pinmux_get_func_name,
.get_function_groups = sirfsoc_pinmux_get_groups, .get_function_groups = sirfsoc_pinmux_get_groups,
.gpio_request_enable = sirfsoc_pinmux_request_gpio, .gpio_request_enable = sirfsoc_pinmux_request_gpio,
......
...@@ -23,9 +23,11 @@ ...@@ -23,9 +23,11 @@
#include <linux/io.h> #include <linux/io.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/pinctrl/machine.h>
#include <linux/pinctrl/pinctrl.h> #include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h> #include <linux/pinctrl/pinmux.h>
#include <linux/pinctrl/pinconf.h> #include <linux/pinctrl/pinconf.h>
#include <linux/slab.h>
#include <mach/pinconf-tegra.h> #include <mach/pinconf-tegra.h>
...@@ -53,15 +55,11 @@ static inline void pmx_writel(struct tegra_pmx *pmx, u32 val, u32 bank, u32 reg) ...@@ -53,15 +55,11 @@ static inline void pmx_writel(struct tegra_pmx *pmx, u32 val, u32 bank, u32 reg)
writel(val, pmx->regs[bank] + reg); writel(val, pmx->regs[bank] + reg);
} }
static int tegra_pinctrl_list_groups(struct pinctrl_dev *pctldev, static int tegra_pinctrl_get_groups_count(struct pinctrl_dev *pctldev)
unsigned group)
{ {
struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
if (group >= pmx->soc->ngroups) return pmx->soc->ngroups;
return -EINVAL;
return 0;
} }
static const char *tegra_pinctrl_get_group_name(struct pinctrl_dev *pctldev, static const char *tegra_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
...@@ -69,9 +67,6 @@ static const char *tegra_pinctrl_get_group_name(struct pinctrl_dev *pctldev, ...@@ -69,9 +67,6 @@ static const char *tegra_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
{ {
struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
if (group >= pmx->soc->ngroups)
return NULL;
return pmx->soc->groups[group].name; return pmx->soc->groups[group].name;
} }
...@@ -82,9 +77,6 @@ static int tegra_pinctrl_get_group_pins(struct pinctrl_dev *pctldev, ...@@ -82,9 +77,6 @@ static int tegra_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
{ {
struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
if (group >= pmx->soc->ngroups)
return -EINVAL;
*pins = pmx->soc->groups[group].pins; *pins = pmx->soc->groups[group].pins;
*num_pins = pmx->soc->groups[group].npins; *num_pins = pmx->soc->groups[group].npins;
...@@ -98,22 +90,221 @@ static void tegra_pinctrl_pin_dbg_show(struct pinctrl_dev *pctldev, ...@@ -98,22 +90,221 @@ static void tegra_pinctrl_pin_dbg_show(struct pinctrl_dev *pctldev,
seq_printf(s, " " DRIVER_NAME); seq_printf(s, " " DRIVER_NAME);
} }
static int reserve_map(struct pinctrl_map **map, unsigned *reserved_maps,
unsigned *num_maps, unsigned reserve)
{
unsigned old_num = *reserved_maps;
unsigned new_num = *num_maps + reserve;
struct pinctrl_map *new_map;
if (old_num >= new_num)
return 0;
new_map = krealloc(*map, sizeof(*new_map) * new_num, GFP_KERNEL);
if (!new_map)
return -ENOMEM;
memset(new_map + old_num, 0, (new_num - old_num) * sizeof(*new_map));
*map = new_map;
*reserved_maps = new_num;
return 0;
}
static int add_map_mux(struct pinctrl_map **map, unsigned *reserved_maps,
unsigned *num_maps, const char *group,
const char *function)
{
if (*num_maps == *reserved_maps)
return -ENOSPC;
(*map)[*num_maps].type = PIN_MAP_TYPE_MUX_GROUP;
(*map)[*num_maps].data.mux.group = group;
(*map)[*num_maps].data.mux.function = function;
(*num_maps)++;
return 0;
}
static int add_map_configs(struct pinctrl_map **map, unsigned *reserved_maps,
unsigned *num_maps, const char *group,
unsigned long *configs, unsigned num_configs)
{
unsigned long *dup_configs;
if (*num_maps == *reserved_maps)
return -ENOSPC;
dup_configs = kmemdup(configs, num_configs * sizeof(*dup_configs),
GFP_KERNEL);
if (!dup_configs)
return -ENOMEM;
(*map)[*num_maps].type = PIN_MAP_TYPE_CONFIGS_GROUP;
(*map)[*num_maps].data.configs.group_or_pin = group;
(*map)[*num_maps].data.configs.configs = dup_configs;
(*map)[*num_maps].data.configs.num_configs = num_configs;
(*num_maps)++;
return 0;
}
static int add_config(unsigned long **configs, unsigned *num_configs,
unsigned long config)
{
unsigned old_num = *num_configs;
unsigned new_num = old_num + 1;
unsigned long *new_configs;
new_configs = krealloc(*configs, sizeof(*new_configs) * new_num,
GFP_KERNEL);
if (!new_configs)
return -ENOMEM;
new_configs[old_num] = config;
*configs = new_configs;
*num_configs = new_num;
return 0;
}
void tegra_pinctrl_dt_free_map(struct pinctrl_dev *pctldev,
struct pinctrl_map *map, unsigned num_maps)
{
int i;
for (i = 0; i < num_maps; i++)
if (map[i].type == PIN_MAP_TYPE_CONFIGS_GROUP)
kfree(map[i].data.configs.configs);
kfree(map);
}
static const struct cfg_param {
const char *property;
enum tegra_pinconf_param param;
} cfg_params[] = {
{"nvidia,pull", TEGRA_PINCONF_PARAM_PULL},
{"nvidia,tristate", TEGRA_PINCONF_PARAM_TRISTATE},
{"nvidia,enable-input", TEGRA_PINCONF_PARAM_ENABLE_INPUT},
{"nvidia,open-drain", TEGRA_PINCONF_PARAM_OPEN_DRAIN},
{"nvidia,lock", TEGRA_PINCONF_PARAM_LOCK},
{"nvidia,io-reset", TEGRA_PINCONF_PARAM_IORESET},
{"nvidia,high-speed-mode", TEGRA_PINCONF_PARAM_HIGH_SPEED_MODE},
{"nvidia,schmitt", TEGRA_PINCONF_PARAM_SCHMITT},
{"nvidia,low-power-mode", TEGRA_PINCONF_PARAM_LOW_POWER_MODE},
{"nvidia,pull-down-strength", TEGRA_PINCONF_PARAM_DRIVE_DOWN_STRENGTH},
{"nvidia,pull-up-strength", TEGRA_PINCONF_PARAM_DRIVE_UP_STRENGTH},
{"nvidia,slew-rate-falling", TEGRA_PINCONF_PARAM_SLEW_RATE_FALLING},
{"nvidia,slew-rate-rising", TEGRA_PINCONF_PARAM_SLEW_RATE_RISING},
};
int tegra_pinctrl_dt_subnode_to_map(struct device_node *np,
struct pinctrl_map **map,
unsigned *reserved_maps,
unsigned *num_maps)
{
int ret, i;
const char *function;
u32 val;
unsigned long config;
unsigned long *configs = NULL;
unsigned num_configs = 0;
unsigned reserve;
struct property *prop;
const char *group;
ret = of_property_read_string(np, "nvidia,function", &function);
if (ret < 0)
function = NULL;
for (i = 0; i < ARRAY_SIZE(cfg_params); i++) {
ret = of_property_read_u32(np, cfg_params[i].property, &val);
if (!ret) {
config = TEGRA_PINCONF_PACK(cfg_params[i].param, val);
ret = add_config(&configs, &num_configs, config);
if (ret < 0)
goto exit;
}
}
reserve = 0;
if (function != NULL)
reserve++;
if (num_configs)
reserve++;
ret = of_property_count_strings(np, "nvidia,pins");
if (ret < 0)
goto exit;
reserve *= ret;
ret = reserve_map(map, reserved_maps, num_maps, reserve);
if (ret < 0)
goto exit;
of_property_for_each_string(np, "nvidia,pins", prop, group) {
if (function) {
ret = add_map_mux(map, reserved_maps, num_maps,
group, function);
if (ret < 0)
goto exit;
}
if (num_configs) {
ret = add_map_configs(map, reserved_maps, num_maps,
group, configs, num_configs);
if (ret < 0)
goto exit;
}
}
ret = 0;
exit:
kfree(configs);
return ret;
}
int tegra_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
struct device_node *np_config,
struct pinctrl_map **map, unsigned *num_maps)
{
unsigned reserved_maps;
struct device_node *np;
int ret;
reserved_maps = 0;
*map = NULL;
*num_maps = 0;
for_each_child_of_node(np_config, np) {
ret = tegra_pinctrl_dt_subnode_to_map(np, map, &reserved_maps,
num_maps);
if (ret < 0) {
tegra_pinctrl_dt_free_map(pctldev, *map, *num_maps);
return ret;
}
}
return 0;
}
static struct pinctrl_ops tegra_pinctrl_ops = { static struct pinctrl_ops tegra_pinctrl_ops = {
.list_groups = tegra_pinctrl_list_groups, .get_groups_count = tegra_pinctrl_get_groups_count,
.get_group_name = tegra_pinctrl_get_group_name, .get_group_name = tegra_pinctrl_get_group_name,
.get_group_pins = tegra_pinctrl_get_group_pins, .get_group_pins = tegra_pinctrl_get_group_pins,
.pin_dbg_show = tegra_pinctrl_pin_dbg_show, .pin_dbg_show = tegra_pinctrl_pin_dbg_show,
.dt_node_to_map = tegra_pinctrl_dt_node_to_map,
.dt_free_map = tegra_pinctrl_dt_free_map,
}; };
static int tegra_pinctrl_list_funcs(struct pinctrl_dev *pctldev, static int tegra_pinctrl_get_funcs_count(struct pinctrl_dev *pctldev)
unsigned function)
{ {
struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
if (function >= pmx->soc->nfunctions) return pmx->soc->nfunctions;
return -EINVAL;
return 0;
} }
static const char *tegra_pinctrl_get_func_name(struct pinctrl_dev *pctldev, static const char *tegra_pinctrl_get_func_name(struct pinctrl_dev *pctldev,
...@@ -121,9 +312,6 @@ static const char *tegra_pinctrl_get_func_name(struct pinctrl_dev *pctldev, ...@@ -121,9 +312,6 @@ static const char *tegra_pinctrl_get_func_name(struct pinctrl_dev *pctldev,
{ {
struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
if (function >= pmx->soc->nfunctions)
return NULL;
return pmx->soc->functions[function].name; return pmx->soc->functions[function].name;
} }
...@@ -134,9 +322,6 @@ static int tegra_pinctrl_get_func_groups(struct pinctrl_dev *pctldev, ...@@ -134,9 +322,6 @@ static int tegra_pinctrl_get_func_groups(struct pinctrl_dev *pctldev,
{ {
struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
if (function >= pmx->soc->nfunctions)
return -EINVAL;
*groups = pmx->soc->functions[function].groups; *groups = pmx->soc->functions[function].groups;
*num_groups = pmx->soc->functions[function].ngroups; *num_groups = pmx->soc->functions[function].ngroups;
...@@ -151,8 +336,6 @@ static int tegra_pinctrl_enable(struct pinctrl_dev *pctldev, unsigned function, ...@@ -151,8 +336,6 @@ static int tegra_pinctrl_enable(struct pinctrl_dev *pctldev, unsigned function,
int i; int i;
u32 val; u32 val;
if (group >= pmx->soc->ngroups)
return -EINVAL;
g = &pmx->soc->groups[group]; g = &pmx->soc->groups[group];
if (g->mux_reg < 0) if (g->mux_reg < 0)
...@@ -180,8 +363,6 @@ static void tegra_pinctrl_disable(struct pinctrl_dev *pctldev, ...@@ -180,8 +363,6 @@ static void tegra_pinctrl_disable(struct pinctrl_dev *pctldev,
const struct tegra_pingroup *g; const struct tegra_pingroup *g;
u32 val; u32 val;
if (group >= pmx->soc->ngroups)
return;
g = &pmx->soc->groups[group]; g = &pmx->soc->groups[group];
if (g->mux_reg < 0) if (g->mux_reg < 0)
...@@ -194,7 +375,7 @@ static void tegra_pinctrl_disable(struct pinctrl_dev *pctldev, ...@@ -194,7 +375,7 @@ static void tegra_pinctrl_disable(struct pinctrl_dev *pctldev,
} }
static struct pinmux_ops tegra_pinmux_ops = { static struct pinmux_ops tegra_pinmux_ops = {
.list_functions = tegra_pinctrl_list_funcs, .get_functions_count = tegra_pinctrl_get_funcs_count,
.get_function_name = tegra_pinctrl_get_func_name, .get_function_name = tegra_pinctrl_get_func_name,
.get_function_groups = tegra_pinctrl_get_func_groups, .get_function_groups = tegra_pinctrl_get_func_groups,
.enable = tegra_pinctrl_enable, .enable = tegra_pinctrl_enable,
...@@ -324,8 +505,6 @@ static int tegra_pinconf_group_get(struct pinctrl_dev *pctldev, ...@@ -324,8 +505,6 @@ static int tegra_pinconf_group_get(struct pinctrl_dev *pctldev,
s16 reg; s16 reg;
u32 val, mask; u32 val, mask;
if (group >= pmx->soc->ngroups)
return -EINVAL;
g = &pmx->soc->groups[group]; g = &pmx->soc->groups[group];
ret = tegra_pinconf_reg(pmx, g, param, &bank, &reg, &bit, &width); ret = tegra_pinconf_reg(pmx, g, param, &bank, &reg, &bit, &width);
...@@ -353,8 +532,6 @@ static int tegra_pinconf_group_set(struct pinctrl_dev *pctldev, ...@@ -353,8 +532,6 @@ static int tegra_pinconf_group_set(struct pinctrl_dev *pctldev,
s16 reg; s16 reg;
u32 val, mask; u32 val, mask;
if (group >= pmx->soc->ngroups)
return -EINVAL;
g = &pmx->soc->groups[group]; g = &pmx->soc->groups[group];
ret = tegra_pinconf_reg(pmx, g, param, &bank, &reg, &bit, &width); ret = tegra_pinconf_reg(pmx, g, param, &bank, &reg, &bit, &width);
......
...@@ -836,18 +836,14 @@ static const struct u300_pin_group u300_pin_groups[] = { ...@@ -836,18 +836,14 @@ static const struct u300_pin_group u300_pin_groups[] = {
}, },
}; };
static int u300_list_groups(struct pinctrl_dev *pctldev, unsigned selector) static int u300_get_groups_count(struct pinctrl_dev *pctldev)
{ {
if (selector >= ARRAY_SIZE(u300_pin_groups)) return ARRAY_SIZE(u300_pin_groups);
return -EINVAL;
return 0;
} }
static const char *u300_get_group_name(struct pinctrl_dev *pctldev, static const char *u300_get_group_name(struct pinctrl_dev *pctldev,
unsigned selector) unsigned selector)
{ {
if (selector >= ARRAY_SIZE(u300_pin_groups))
return NULL;
return u300_pin_groups[selector].name; return u300_pin_groups[selector].name;
} }
...@@ -855,8 +851,6 @@ static int u300_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector, ...@@ -855,8 +851,6 @@ static int u300_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector,
const unsigned **pins, const unsigned **pins,
unsigned *num_pins) unsigned *num_pins)
{ {
if (selector >= ARRAY_SIZE(u300_pin_groups))
return -EINVAL;
*pins = u300_pin_groups[selector].pins; *pins = u300_pin_groups[selector].pins;
*num_pins = u300_pin_groups[selector].num_pins; *num_pins = u300_pin_groups[selector].num_pins;
return 0; return 0;
...@@ -869,7 +863,7 @@ static void u300_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s, ...@@ -869,7 +863,7 @@ static void u300_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
} }
static struct pinctrl_ops u300_pctrl_ops = { static struct pinctrl_ops u300_pctrl_ops = {
.list_groups = u300_list_groups, .get_groups_count = u300_get_groups_count,
.get_group_name = u300_get_group_name, .get_group_name = u300_get_group_name,
.get_group_pins = u300_get_group_pins, .get_group_pins = u300_get_group_pins,
.pin_dbg_show = u300_pin_dbg_show, .pin_dbg_show = u300_pin_dbg_show,
...@@ -991,11 +985,9 @@ static void u300_pmx_disable(struct pinctrl_dev *pctldev, unsigned selector, ...@@ -991,11 +985,9 @@ static void u300_pmx_disable(struct pinctrl_dev *pctldev, unsigned selector,
u300_pmx_endisable(upmx, selector, false); u300_pmx_endisable(upmx, selector, false);
} }
static int u300_pmx_list_funcs(struct pinctrl_dev *pctldev, unsigned selector) static int u300_pmx_get_funcs_count(struct pinctrl_dev *pctldev)
{ {
if (selector >= ARRAY_SIZE(u300_pmx_functions)) return ARRAY_SIZE(u300_pmx_functions);
return -EINVAL;
return 0;
} }
static const char *u300_pmx_get_func_name(struct pinctrl_dev *pctldev, static const char *u300_pmx_get_func_name(struct pinctrl_dev *pctldev,
...@@ -1014,7 +1006,7 @@ static int u300_pmx_get_groups(struct pinctrl_dev *pctldev, unsigned selector, ...@@ -1014,7 +1006,7 @@ static int u300_pmx_get_groups(struct pinctrl_dev *pctldev, unsigned selector,
} }
static struct pinmux_ops u300_pmx_ops = { static struct pinmux_ops u300_pmx_ops = {
.list_functions = u300_pmx_list_funcs, .get_functions_count = u300_pmx_get_funcs_count,
.get_function_name = u300_pmx_get_func_name, .get_function_name = u300_pmx_get_func_name,
.get_function_groups = u300_pmx_get_groups, .get_function_groups = u300_pmx_get_groups,
.enable = u300_pmx_enable, .enable = u300_pmx_enable,
......
...@@ -33,10 +33,12 @@ ...@@ -33,10 +33,12 @@
int pinmux_check_ops(struct pinctrl_dev *pctldev) int pinmux_check_ops(struct pinctrl_dev *pctldev)
{ {
const struct pinmux_ops *ops = pctldev->desc->pmxops; const struct pinmux_ops *ops = pctldev->desc->pmxops;
unsigned nfuncs;
unsigned selector = 0; unsigned selector = 0;
/* Check that we implement required operations */ /* Check that we implement required operations */
if (!ops->list_functions || if (!ops ||
!ops->get_functions_count ||
!ops->get_function_name || !ops->get_function_name ||
!ops->get_function_groups || !ops->get_function_groups ||
!ops->enable || !ops->enable ||
...@@ -44,11 +46,12 @@ int pinmux_check_ops(struct pinctrl_dev *pctldev) ...@@ -44,11 +46,12 @@ int pinmux_check_ops(struct pinctrl_dev *pctldev)
return -EINVAL; return -EINVAL;
/* Check that all functions registered have names */ /* Check that all functions registered have names */
while (ops->list_functions(pctldev, selector) >= 0) { nfuncs = ops->get_functions_count(pctldev);
while (selector < nfuncs) {
const char *fname = ops->get_function_name(pctldev, const char *fname = ops->get_function_name(pctldev,
selector); selector);
if (!fname) { if (!fname) {
pr_err("pinmux ops has no name for function%u\n", dev_err(pctldev->dev, "pinmux ops has no name for function%u\n",
selector); selector);
return -EINVAL; return -EINVAL;
} }
...@@ -85,8 +88,6 @@ static int pin_request(struct pinctrl_dev *pctldev, ...@@ -85,8 +88,6 @@ static int pin_request(struct pinctrl_dev *pctldev,
const struct pinmux_ops *ops = pctldev->desc->pmxops; const struct pinmux_ops *ops = pctldev->desc->pmxops;
int status = -EINVAL; int status = -EINVAL;
dev_dbg(pctldev->dev, "request pin %d for %s\n", pin, owner);
desc = pin_desc_get(pctldev, pin); desc = pin_desc_get(pctldev, pin);
if (desc == NULL) { if (desc == NULL) {
dev_err(pctldev->dev, dev_err(pctldev->dev,
...@@ -94,6 +95,9 @@ static int pin_request(struct pinctrl_dev *pctldev, ...@@ -94,6 +95,9 @@ static int pin_request(struct pinctrl_dev *pctldev,
goto out; goto out;
} }
dev_dbg(pctldev->dev, "request pin %d (%s) for %s\n",
pin, desc->name, owner);
if (gpio_range) { if (gpio_range) {
/* There's no need to support multiple GPIO requests */ /* There's no need to support multiple GPIO requests */
if (desc->gpio_owner) { if (desc->gpio_owner) {
...@@ -287,10 +291,11 @@ static int pinmux_func_name_to_selector(struct pinctrl_dev *pctldev, ...@@ -287,10 +291,11 @@ static int pinmux_func_name_to_selector(struct pinctrl_dev *pctldev,
const char *function) const char *function)
{ {
const struct pinmux_ops *ops = pctldev->desc->pmxops; const struct pinmux_ops *ops = pctldev->desc->pmxops;
unsigned nfuncs = ops->get_functions_count(pctldev);
unsigned selector = 0; unsigned selector = 0;
/* See if this pctldev has this function */ /* See if this pctldev has this function */
while (ops->list_functions(pctldev, selector) >= 0) { while (selector < nfuncs) {
const char *fname = ops->get_function_name(pctldev, const char *fname = ops->get_function_name(pctldev,
selector); selector);
...@@ -319,6 +324,11 @@ int pinmux_map_to_setting(struct pinctrl_map const *map, ...@@ -319,6 +324,11 @@ int pinmux_map_to_setting(struct pinctrl_map const *map,
const unsigned *pins; const unsigned *pins;
unsigned num_pins; unsigned num_pins;
if (!pmxops) {
dev_err(pctldev->dev, "does not support mux function\n");
return -EINVAL;
}
setting->data.mux.func = setting->data.mux.func =
pinmux_func_name_to_selector(pctldev, map->data.mux.function); pinmux_func_name_to_selector(pctldev, map->data.mux.function);
if (setting->data.mux.func < 0) if (setting->data.mux.func < 0)
...@@ -477,11 +487,15 @@ static int pinmux_functions_show(struct seq_file *s, void *what) ...@@ -477,11 +487,15 @@ static int pinmux_functions_show(struct seq_file *s, void *what)
{ {
struct pinctrl_dev *pctldev = s->private; struct pinctrl_dev *pctldev = s->private;
const struct pinmux_ops *pmxops = pctldev->desc->pmxops; const struct pinmux_ops *pmxops = pctldev->desc->pmxops;
unsigned nfuncs;
unsigned func_selector = 0; unsigned func_selector = 0;
mutex_lock(&pinctrl_mutex); if (!pmxops)
return 0;
while (pmxops->list_functions(pctldev, func_selector) >= 0) { mutex_lock(&pinctrl_mutex);
nfuncs = pmxops->get_functions_count(pctldev);
while (func_selector < nfuncs) {
const char *func = pmxops->get_function_name(pctldev, const char *func = pmxops->get_function_name(pctldev,
func_selector); func_selector);
const char * const *groups; const char * const *groups;
...@@ -515,6 +529,9 @@ static int pinmux_pins_show(struct seq_file *s, void *what) ...@@ -515,6 +529,9 @@ static int pinmux_pins_show(struct seq_file *s, void *what)
const struct pinmux_ops *pmxops = pctldev->desc->pmxops; const struct pinmux_ops *pmxops = pctldev->desc->pmxops;
unsigned i, pin; unsigned i, pin;
if (!pmxops)
return 0;
seq_puts(s, "Pinmux settings per pin\n"); seq_puts(s, "Pinmux settings per pin\n");
seq_puts(s, "Format: pin (name): mux_owner gpio_owner hog?\n"); seq_puts(s, "Format: pin (name): mux_owner gpio_owner hog?\n");
......
...@@ -31,12 +31,6 @@ void pinmux_free_setting(struct pinctrl_setting const *setting); ...@@ -31,12 +31,6 @@ void pinmux_free_setting(struct pinctrl_setting const *setting);
int pinmux_enable_setting(struct pinctrl_setting const *setting); int pinmux_enable_setting(struct pinctrl_setting const *setting);
void pinmux_disable_setting(struct pinctrl_setting const *setting); void pinmux_disable_setting(struct pinctrl_setting const *setting);
void pinmux_show_map(struct seq_file *s, struct pinctrl_map const *map);
void pinmux_show_setting(struct seq_file *s,
struct pinctrl_setting const *setting);
void pinmux_init_device_debugfs(struct dentry *devroot,
struct pinctrl_dev *pctldev);
#else #else
static inline int pinmux_check_ops(struct pinctrl_dev *pctldev) static inline int pinmux_check_ops(struct pinctrl_dev *pctldev)
...@@ -89,6 +83,18 @@ static inline void pinmux_disable_setting( ...@@ -89,6 +83,18 @@ static inline void pinmux_disable_setting(
{ {
} }
#endif
#if defined(CONFIG_PINMUX) && defined(CONFIG_DEBUG_FS)
void pinmux_show_map(struct seq_file *s, struct pinctrl_map const *map);
void pinmux_show_setting(struct seq_file *s,
struct pinctrl_setting const *setting);
void pinmux_init_device_debugfs(struct dentry *devroot,
struct pinctrl_dev *pctldev);
#else
static inline void pinmux_show_map(struct seq_file *s, static inline void pinmux_show_map(struct seq_file *s,
struct pinctrl_map const *map) struct pinctrl_map const *map)
{ {
......
...@@ -259,6 +259,37 @@ extern void of_detach_node(struct device_node *); ...@@ -259,6 +259,37 @@ extern void of_detach_node(struct device_node *);
#endif #endif
#define of_match_ptr(_ptr) (_ptr) #define of_match_ptr(_ptr) (_ptr)
/*
* struct property *prop;
* const __be32 *p;
* u32 u;
*
* of_property_for_each_u32(np, "propname", prop, p, u)
* printk("U32 value: %x\n", u);
*/
const __be32 *of_prop_next_u32(struct property *prop, const __be32 *cur,
u32 *pu);
#define of_property_for_each_u32(np, propname, prop, p, u) \
for (prop = of_find_property(np, propname, NULL), \
p = of_prop_next_u32(prop, NULL, &u); \
p; \
p = of_prop_next_u32(prop, p, &u))
/*
* struct property *prop;
* const char *s;
*
* of_property_for_each_string(np, "propname", prop, s)
* printk("String value: %s\n", s);
*/
const char *of_prop_next_string(struct property *prop, const char *cur);
#define of_property_for_each_string(np, propname, prop, s) \
for (prop = of_find_property(np, propname, NULL), \
s = of_prop_next_string(prop, NULL); \
s; \
s = of_prop_next_string(prop, s))
#else /* CONFIG_OF */ #else /* CONFIG_OF */
static inline bool of_have_populated_dt(void) static inline bool of_have_populated_dt(void)
...@@ -349,6 +380,10 @@ static inline int of_machine_is_compatible(const char *compat) ...@@ -349,6 +380,10 @@ static inline int of_machine_is_compatible(const char *compat)
#define of_match_ptr(_ptr) NULL #define of_match_ptr(_ptr) NULL
#define of_match_node(_matches, _node) NULL #define of_match_node(_matches, _node) NULL
#define of_property_for_each_u32(np, propname, prop, p, u) \
while (0)
#define of_property_for_each_string(np, propname, prop, s) \
while (0)
#endif /* CONFIG_OF */ #endif /* CONFIG_OF */
/** /**
......
...@@ -36,6 +36,9 @@ extern struct pinctrl_state * __must_check pinctrl_lookup_state( ...@@ -36,6 +36,9 @@ extern struct pinctrl_state * __must_check pinctrl_lookup_state(
const char *name); const char *name);
extern int pinctrl_select_state(struct pinctrl *p, struct pinctrl_state *s); extern int pinctrl_select_state(struct pinctrl *p, struct pinctrl_state *s);
extern struct pinctrl * __must_check devm_pinctrl_get(struct device *dev);
extern void devm_pinctrl_put(struct pinctrl *p);
#else /* !CONFIG_PINCTRL */ #else /* !CONFIG_PINCTRL */
static inline int pinctrl_request_gpio(unsigned gpio) static inline int pinctrl_request_gpio(unsigned gpio)
...@@ -79,6 +82,15 @@ static inline int pinctrl_select_state(struct pinctrl *p, ...@@ -79,6 +82,15 @@ static inline int pinctrl_select_state(struct pinctrl *p,
return 0; return 0;
} }
static inline struct pinctrl * __must_check devm_pinctrl_get(struct device *dev)
{
return NULL;
}
static inline void devm_pinctrl_put(struct pinctrl *p)
{
}
#endif /* CONFIG_PINCTRL */ #endif /* CONFIG_PINCTRL */
static inline struct pinctrl * __must_check pinctrl_get_select( static inline struct pinctrl * __must_check pinctrl_get_select(
...@@ -113,6 +125,38 @@ static inline struct pinctrl * __must_check pinctrl_get_select_default( ...@@ -113,6 +125,38 @@ static inline struct pinctrl * __must_check pinctrl_get_select_default(
return pinctrl_get_select(dev, PINCTRL_STATE_DEFAULT); return pinctrl_get_select(dev, PINCTRL_STATE_DEFAULT);
} }
static inline struct pinctrl * __must_check devm_pinctrl_get_select(
struct device *dev, const char *name)
{
struct pinctrl *p;
struct pinctrl_state *s;
int ret;
p = devm_pinctrl_get(dev);
if (IS_ERR(p))
return p;
s = pinctrl_lookup_state(p, name);
if (IS_ERR(s)) {
devm_pinctrl_put(p);
return ERR_PTR(PTR_ERR(s));
}
ret = pinctrl_select_state(p, s);
if (ret < 0) {
devm_pinctrl_put(p);
return ERR_PTR(ret);
}
return p;
}
static inline struct pinctrl * __must_check devm_pinctrl_get_select_default(
struct device *dev)
{
return devm_pinctrl_get_select(dev, PINCTRL_STATE_DEFAULT);
}
#ifdef CONFIG_PINCONF #ifdef CONFIG_PINCONF
extern int pin_config_get(const char *dev_name, const char *name, extern int pin_config_get(const char *dev_name, const char *name,
......
...@@ -33,6 +33,8 @@ struct seq_file; ...@@ -33,6 +33,8 @@ struct seq_file;
* per-device info for a certain pin in debugfs * per-device info for a certain pin in debugfs
* @pin_config_group_dbg_show: optional debugfs display hook that will provide * @pin_config_group_dbg_show: optional debugfs display hook that will provide
* per-device info for a certain group in debugfs * per-device info for a certain group in debugfs
* @pin_config_config_dbg_show: optional debugfs display hook that will decode
* and display a driver's pin configuration parameter
*/ */
struct pinconf_ops { struct pinconf_ops {
#ifdef CONFIG_GENERIC_PINCONF #ifdef CONFIG_GENERIC_PINCONF
...@@ -56,6 +58,9 @@ struct pinconf_ops { ...@@ -56,6 +58,9 @@ struct pinconf_ops {
void (*pin_config_group_dbg_show) (struct pinctrl_dev *pctldev, void (*pin_config_group_dbg_show) (struct pinctrl_dev *pctldev,
struct seq_file *s, struct seq_file *s,
unsigned selector); unsigned selector);
void (*pin_config_config_dbg_show) (struct pinctrl_dev *pctldev,
struct seq_file *s,
unsigned long config);
}; };
#endif #endif
......
...@@ -21,9 +21,11 @@ ...@@ -21,9 +21,11 @@
struct device; struct device;
struct pinctrl_dev; struct pinctrl_dev;
struct pinctrl_map;
struct pinmux_ops; struct pinmux_ops;
struct pinconf_ops; struct pinconf_ops;
struct gpio_chip; struct gpio_chip;
struct device_node;
/** /**
* struct pinctrl_pin_desc - boards/machines provide information on their * struct pinctrl_pin_desc - boards/machines provide information on their
...@@ -64,9 +66,7 @@ struct pinctrl_gpio_range { ...@@ -64,9 +66,7 @@ struct pinctrl_gpio_range {
/** /**
* struct pinctrl_ops - global pin control operations, to be implemented by * struct pinctrl_ops - global pin control operations, to be implemented by
* pin controller drivers. * pin controller drivers.
* @list_groups: list the number of selectable named groups available * @get_groups_count: Returns the count of total number of groups registered.
* in this pinmux driver, the core will begin on 0 and call this
* repeatedly as long as it returns >= 0 to enumerate the groups
* @get_group_name: return the group name of the pin group * @get_group_name: return the group name of the pin group
* @get_group_pins: return an array of pins corresponding to a certain * @get_group_pins: return an array of pins corresponding to a certain
* group selector @pins, and the size of the array in @num_pins * group selector @pins, and the size of the array in @num_pins
...@@ -74,7 +74,7 @@ struct pinctrl_gpio_range { ...@@ -74,7 +74,7 @@ struct pinctrl_gpio_range {
* info for a certain pin in debugfs * info for a certain pin in debugfs
*/ */
struct pinctrl_ops { struct pinctrl_ops {
int (*list_groups) (struct pinctrl_dev *pctldev, unsigned selector); int (*get_groups_count) (struct pinctrl_dev *pctldev);
const char *(*get_group_name) (struct pinctrl_dev *pctldev, const char *(*get_group_name) (struct pinctrl_dev *pctldev,
unsigned selector); unsigned selector);
int (*get_group_pins) (struct pinctrl_dev *pctldev, int (*get_group_pins) (struct pinctrl_dev *pctldev,
...@@ -83,6 +83,11 @@ struct pinctrl_ops { ...@@ -83,6 +83,11 @@ struct pinctrl_ops {
unsigned *num_pins); unsigned *num_pins);
void (*pin_dbg_show) (struct pinctrl_dev *pctldev, struct seq_file *s, void (*pin_dbg_show) (struct pinctrl_dev *pctldev, struct seq_file *s,
unsigned offset); unsigned offset);
int (*dt_node_to_map) (struct pinctrl_dev *pctldev,
struct device_node *np_config,
struct pinctrl_map **map, unsigned *num_maps);
void (*dt_free_map) (struct pinctrl_dev *pctldev,
struct pinctrl_map *map, unsigned num_maps);
}; };
/** /**
......
...@@ -29,9 +29,8 @@ struct pinctrl_dev; ...@@ -29,9 +29,8 @@ struct pinctrl_dev;
* is allowed to answer "no" by returning a negative error code * is allowed to answer "no" by returning a negative error code
* @free: the reverse function of the request() callback, frees a pin after * @free: the reverse function of the request() callback, frees a pin after
* being requested * being requested
* @list_functions: list the number of selectable named functions available * @get_functions_count: returns number of selectable named functions available
* in this pinmux driver, the core will begin on 0 and call this * in this pinmux driver
* repeatedly as long as it returns >= 0 to enumerate mux settings
* @get_function_name: return the function name of the muxing selector, * @get_function_name: return the function name of the muxing selector,
* called by the core to figure out which mux setting it shall map a * called by the core to figure out which mux setting it shall map a
* certain device to * certain device to
...@@ -62,7 +61,7 @@ struct pinctrl_dev; ...@@ -62,7 +61,7 @@ struct pinctrl_dev;
struct pinmux_ops { struct pinmux_ops {
int (*request) (struct pinctrl_dev *pctldev, unsigned offset); int (*request) (struct pinctrl_dev *pctldev, unsigned offset);
int (*free) (struct pinctrl_dev *pctldev, unsigned offset); int (*free) (struct pinctrl_dev *pctldev, unsigned offset);
int (*list_functions) (struct pinctrl_dev *pctldev, unsigned selector); int (*get_functions_count) (struct pinctrl_dev *pctldev);
const char *(*get_function_name) (struct pinctrl_dev *pctldev, const char *(*get_function_name) (struct pinctrl_dev *pctldev,
unsigned selector); unsigned selector);
int (*get_function_groups) (struct pinctrl_dev *pctldev, int (*get_function_groups) (struct pinctrl_dev *pctldev,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment