···11+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)22+%YAML 1.233+---44+$id: http://devicetree.org/schemas/net/lantiq,pef2256.yaml#55+$schema: http://devicetree.org/meta-schemas/core.yaml#66+77+title: Lantiq PEF225688+99+maintainers:1010+ - Herve Codina <herve.codina@bootlin.com>1111+1212+description:1313+ The Lantiq PEF2256, also known as Infineon PEF2256 or FALC56, is a framer and1414+ line interface component designed to fulfill all required interfacing between1515+ an analog E1/T1/J1 line and the digital PCM system highway/H.100 bus.1616+1717+properties:1818+ compatible:1919+ items:2020+ - const: lantiq,pef22562121+2222+ reg:2323+ maxItems: 12424+2525+ clocks:2626+ items:2727+ - description: Master Clock2828+ - description: System Clock Receive2929+ - description: System Clock Transmit3030+3131+ clock-names:3232+ items:3333+ - const: mclk3434+ - const: sclkr3535+ - const: sclkx3636+3737+ interrupts:3838+ maxItems: 13939+4040+ reset-gpios:4141+ description:4242+ GPIO used to reset the device.4343+ maxItems: 14444+4545+ pinctrl:4646+ $ref: /schemas/pinctrl/pinctrl.yaml#4747+ additionalProperties: false4848+4949+ patternProperties:5050+ '-pins$':5151+ type: object5252+ $ref: /schemas/pinctrl/pinmux-node.yaml#5353+ additionalProperties: false5454+5555+ properties:5656+ pins:5757+ enum: [ RPA, RPB, RPC, RPD, XPA, XPB, XPC, XPD ]5858+5959+ function:6060+ enum: [ SYPR, RFM, RFMB, RSIGM, RSIG, DLR, FREEZE, RFSP, LOS,6161+ SYPX, XFMS, XSIG, TCLK, XMFB, XSIGM, DLX, XCLK, XLT,6262+ GPI, GPOH, GPOL ]6363+6464+ required:6565+ - pins6666+ - function6767+6868+ lantiq,data-rate-bps:6969+ enum: [2048000, 4096000, 8192000, 16384000]7070+ default: 20480007171+ description:7272+ Data rate (bit per seconds) on the system highway.7373+7474+ lantiq,clock-falling-edge:7575+ $ref: /schemas/types.yaml#/definitions/flag7676+ description:7777+ Data is sent on falling edge of the clock (and received on the rising7878+ edge). If 'clock-falling-edge' is not present, data is sent on the7979+ rising edge (and received on the falling edge).8080+8181+ lantiq,channel-phase:8282+ $ref: /schemas/types.yaml#/definitions/uint328383+ enum: [0, 1, 2, 3, 4, 5, 6, 7]8484+ default: 08585+ description: |8686+ The pef2256 delivers a full frame (32 8-bit time-slots in E1 and 24 8-bit8787+ time-slots 8 8-bit signaling in E1/J1) every 125us. This lead to a data8888+ rate of 2048000 bit/s. When lantiq,data-rate-bps is more than 20480008989+ bit/s, the data (all 32 8-bit) present in the frame are interleave with9090+ unused time-slots. The lantiq,channel-phase property allows to set the9191+ correct alignment of the interleave mechanism.9292+ For instance, suppose lantiq,data-rate-bps = 8192000 (ie 4*2048000), and9393+ lantiq,channel-phase = 2, the interleave schema with unused time-slots9494+ (nu) and used time-slots (XX) for TSi is9595+ nu nu XX nu nu nu XX nu nu nu XX nu9696+ <-- TSi --> <- TSi+1 -> <- TSi+2 ->9797+ With lantiq,data-rate-bps = 8192000, and lantiq,channel-phase = 1, the9898+ interleave schema is9999+ nu XX nu nu nu XX nu nu nu XX nu nu100100+ <-- TSi --> <- TSi+1 -> <- TSi+2 ->101101+ With lantiq,data-rate-bps = 4096000 (ie 2*2048000), and102102+ lantiq,channel-phase = 1, the interleave schema is103103+ nu XX nu XX nu XX104104+ <-- TSi --> <- TSi+1 -> <- TSi+2 ->105105+106106+patternProperties:107107+ '^codec(-([0-9]|[1-2][0-9]|3[0-1]))?$':108108+ type: object109109+ $ref: /schemas/sound/dai-common.yaml110110+ unevaluatedProperties: false111111+ description:112112+ Codec provided by the pef2256. This codec allows to use some of the PCM113113+ system highway time-slots as audio channels to transport audio data over114114+ the E1/T1/J1 lines.115115+ The time-slots used by the codec must be set and so, the properties116116+ 'dai-tdm-slot-num', 'dai-tdm-slot-width', 'dai-tdm-slot-tx-mask' and117117+ 'dai-tdm-slot-rx-mask' must be present in the sound card node for118118+ sub-nodes that involve the codec. The codec uses 8-bit time-slots.119119+ 'dai-tdm-tdm-slot-with' must be set to 8.120120+ The tx and rx masks define the pef2256 time-slots assigned to the codec.121121+122122+ properties:123123+ compatible:124124+ const: lantiq,pef2256-codec125125+126126+ '#sound-dai-cells':127127+ const: 0128128+129129+ required:130130+ - compatible131131+ - '#sound-dai-cells'132132+133133+required:134134+ - compatible135135+ - reg136136+ - clocks137137+ - clock-names138138+ - interrupts139139+140140+additionalProperties: false141141+142142+examples:143143+ - |144144+ #include <dt-bindings/gpio/gpio.h>145145+ #include <dt-bindings/interrupt-controller/irq.h>146146+147147+ pef2256: framer@2000000 {148148+ compatible = "lantiq,pef2256";149149+ reg = <0x2000000 0x100>;150150+ interrupts = <8 IRQ_TYPE_LEVEL_LOW>;151151+ interrupt-parent = <&intc>;152152+ clocks = <&clk_mclk>, <&clk_sclkr>, <&clk_sclkx>;153153+ clock-names = "mclk", "sclkr", "sclkx";154154+ reset-gpios = <&gpio 11 GPIO_ACTIVE_LOW>;155155+ lantiq,data-rate-bps = <4096000>;156156+157157+ pinctrl {158158+ pef2256_rpa_sypr: rpa-pins {159159+ pins = "RPA";160160+ function = "SYPR";161161+ };162162+ pef2256_xpa_sypx: xpa-pins {163163+ pins = "XPA";164164+ function = "SYPX";165165+ };166166+ };167167+168168+ pef2256_codec0: codec-0 {169169+ compatible = "lantiq,pef2256-codec";170170+ #sound-dai-cells = <0>;171171+ sound-name-prefix = "PEF2256_0";172172+ };173173+174174+ pef2256_codec1: codec-1 {175175+ compatible = "lantiq,pef2256-codec";176176+ #sound-dai-cells = <0>;177177+ sound-name-prefix = "PEF2256_1";178178+ };179179+ };180180+181181+ sound {182182+ compatible = "simple-audio-card";183183+ #address-cells = <1>;184184+ #size-cells = <0>;185185+ simple-audio-card,dai-link@0 { /* CPU DAI1 - pef2256 codec 1 */186186+ reg = <0>;187187+ cpu {188188+ sound-dai = <&cpu_dai1>;189189+ };190190+ codec {191191+ sound-dai = <&pef2256_codec0>;192192+ dai-tdm-slot-num = <4>;193193+ dai-tdm-slot-width = <8>;194194+ /* TS 1, 2, 3, 4 */195195+ dai-tdm-slot-tx-mask = <0 1 1 1 1>;196196+ dai-tdm-slot-rx-mask = <0 1 1 1 1>;197197+ };198198+ };199199+ simple-audio-card,dai-link@1 { /* CPU DAI2 - pef2256 codec 2 */200200+ reg = <1>;201201+ cpu {202202+ sound-dai = <&cpu_dai2>;203203+ };204204+ codec {205205+ sound-dai = <&pef2256_codec1>;206206+ dai-tdm-slot-num = <4>;207207+ dai-tdm-slot-width = <8>;208208+ /* TS 5, 6, 7, 8 */209209+ dai-tdm-slot-tx-mask = <0 0 0 0 0 1 1 1 1>;210210+ dai-tdm-slot-rx-mask = <0 0 0 0 0 1 1 1 1>;211211+ };212212+ };213213+ };
···11+# SPDX-License-Identifier: GPL-2.0-only22+#33+# FRAMER44+#55+66+menuconfig FRAMER77+ tristate "Framer Subsystem"88+ help99+ A framer is a component in charge of an E1/T1 line interface.1010+ Connected usually to a TDM bus, it converts TDM frames to/from E1/T11111+ frames. It also provides information related to the E1/T1 line.1212+ Used with HDLC, the network can be reached through the E1/T1 line.1313+1414+ This framework is designed to provide a generic interface for framer1515+ devices present in the kernel. This layer will have the generic1616+ API by which framer drivers can create framer using the framer1717+ framework and framer users can obtain reference to the framer.1818+ All the users of this framework should select this config.1919+2020+if FRAMER2121+2222+config GENERIC_FRAMER2323+ bool2424+2525+config FRAMER_PEF22562626+ tristate "Lantiq PEF2256"2727+ depends on OF2828+ depends on HAS_IOMEM2929+ select GENERIC_FRAMER3030+ select MFD_CORE3131+ select REGMAP_MMIO3232+ help3333+ Enable support for the Lantiq PEF2256 (FALC56) framer.3434+ The PEF2256 is a framer and line interface between analog E1/T1/J13535+ line and a digital PCM bus.3636+3737+ If unsure, say N.3838+3939+ To compile this driver as a module, choose M here: the4040+ module will be called framer-pef2256.4141+4242+endif # FRAMER
+7
drivers/net/wan/framer/Makefile
···11+# SPDX-License-Identifier: GPL-2.022+#33+# Makefile for the framer drivers.44+#55+66+obj-$(CONFIG_GENERIC_FRAMER) += framer-core.o77+obj-$(CONFIG_FRAMER_PEF2256) += pef2256/
+882
drivers/net/wan/framer/framer-core.c
···11+// SPDX-License-Identifier: GPL-2.0-or-later22+/*33+ * Generic Framer framework.44+ *55+ * Copyright 2023 CS GROUP France66+ *77+ * Author: Herve Codina <herve.codina@bootlin.com>88+ */99+1010+#include <linux/device.h>1111+#include <linux/framer/framer.h>1212+#include <linux/framer/framer-provider.h>1313+#include <linux/idr.h>1414+#include <linux/module.h>1515+#include <linux/notifier.h>1616+#include <linux/of.h>1717+#include <linux/pm_runtime.h>1818+#include <linux/regulator/consumer.h>1919+#include <linux/slab.h>2020+2121+static struct class *framer_class;2222+static DEFINE_MUTEX(framer_provider_mutex);2323+static LIST_HEAD(framer_provider_list);2424+static DEFINE_IDA(framer_ida);2525+2626+#define dev_to_framer(a) (container_of((a), struct framer, dev))2727+2828+int framer_pm_runtime_get(struct framer *framer)2929+{3030+ int ret;3131+3232+ if (!pm_runtime_enabled(&framer->dev))3333+ return -EOPNOTSUPP;3434+3535+ ret = pm_runtime_get(&framer->dev);3636+ if (ret < 0 && ret != -EINPROGRESS)3737+ pm_runtime_put_noidle(&framer->dev);3838+3939+ return ret;4040+}4141+EXPORT_SYMBOL_GPL(framer_pm_runtime_get);4242+4343+int framer_pm_runtime_get_sync(struct framer *framer)4444+{4545+ int ret;4646+4747+ if (!pm_runtime_enabled(&framer->dev))4848+ return -EOPNOTSUPP;4949+5050+ ret = pm_runtime_get_sync(&framer->dev);5151+ if (ret < 0)5252+ pm_runtime_put_sync(&framer->dev);5353+5454+ return ret;5555+}5656+EXPORT_SYMBOL_GPL(framer_pm_runtime_get_sync);5757+5858+int framer_pm_runtime_put(struct framer *framer)5959+{6060+ if (!pm_runtime_enabled(&framer->dev))6161+ return -EOPNOTSUPP;6262+6363+ return pm_runtime_put(&framer->dev);6464+}6565+EXPORT_SYMBOL_GPL(framer_pm_runtime_put);6666+6767+int framer_pm_runtime_put_sync(struct framer *framer)6868+{6969+ if (!pm_runtime_enabled(&framer->dev))7070+ return -EOPNOTSUPP;7171+7272+ return pm_runtime_put_sync(&framer->dev);7373+}7474+EXPORT_SYMBOL_GPL(framer_pm_runtime_put_sync);7575+7676+/**7777+ * framer_init - framer internal initialization before framer operation7878+ * @framer: the framer returned by framer_get()7979+ *8080+ * Used to allow framer's driver to perform framer internal initialization,8181+ * such as PLL block powering, clock initialization or anything that's8282+ * is required by the framer to perform the start of operation.8383+ * Must be called before framer_power_on().8484+ *8585+ * Return: %0 if successful, a negative error code otherwise8686+ */8787+int framer_init(struct framer *framer)8888+{8989+ bool start_polling = false;9090+ int ret;9191+9292+ ret = framer_pm_runtime_get_sync(framer);9393+ if (ret < 0 && ret != -EOPNOTSUPP)9494+ return ret;9595+ ret = 0; /* Override possible ret == -EOPNOTSUPP */9696+9797+ mutex_lock(&framer->mutex);9898+ if (framer->power_count > framer->init_count)9999+ dev_warn(&framer->dev, "framer_power_on was called before framer init\n");100100+101101+ if (framer->init_count == 0) {102102+ if (framer->ops->init) {103103+ ret = framer->ops->init(framer);104104+ if (ret < 0) {105105+ dev_err(&framer->dev, "framer init failed --> %d\n", ret);106106+ goto out;107107+ }108108+ }109109+ if (framer->ops->flags & FRAMER_FLAG_POLL_STATUS)110110+ start_polling = true;111111+ }112112+ ++framer->init_count;113113+114114+out:115115+ mutex_unlock(&framer->mutex);116116+117117+ if (!ret && start_polling) {118118+ ret = framer_get_status(framer, &framer->prev_status);119119+ if (ret < 0) {120120+ dev_warn(&framer->dev, "framer get status failed --> %d\n", ret);121121+ /* Will be retried on polling_work */122122+ ret = 0;123123+ }124124+ queue_delayed_work(system_power_efficient_wq, &framer->polling_work, 1 * HZ);125125+ }126126+127127+ framer_pm_runtime_put(framer);128128+ return ret;129129+}130130+EXPORT_SYMBOL_GPL(framer_init);131131+132132+/**133133+ * framer_exit - Framer internal un-initialization134134+ * @framer: the framer returned by framer_get()135135+ *136136+ * Must be called after framer_power_off().137137+ */138138+int framer_exit(struct framer *framer)139139+{140140+ int ret;141141+142142+ ret = framer_pm_runtime_get_sync(framer);143143+ if (ret < 0 && ret != -EOPNOTSUPP)144144+ return ret;145145+ ret = 0; /* Override possible ret == -EOPNOTSUPP */146146+147147+ mutex_lock(&framer->mutex);148148+ --framer->init_count;149149+ if (framer->init_count == 0) {150150+ if (framer->ops->flags & FRAMER_FLAG_POLL_STATUS) {151151+ mutex_unlock(&framer->mutex);152152+ cancel_delayed_work_sync(&framer->polling_work);153153+ mutex_lock(&framer->mutex);154154+ }155155+156156+ if (framer->ops->exit)157157+ framer->ops->exit(framer);158158+ }159159+160160+ mutex_unlock(&framer->mutex);161161+ framer_pm_runtime_put(framer);162162+ return ret;163163+}164164+EXPORT_SYMBOL_GPL(framer_exit);165165+166166+/**167167+ * framer_power_on - Enable the framer and enter proper operation168168+ * @framer: the framer returned by framer_get()169169+ *170170+ * Must be called after framer_init().171171+ *172172+ * Return: %0 if successful, a negative error code otherwise173173+ */174174+int framer_power_on(struct framer *framer)175175+{176176+ int ret;177177+178178+ if (framer->pwr) {179179+ ret = regulator_enable(framer->pwr);180180+ if (ret)181181+ return ret;182182+ }183183+184184+ ret = framer_pm_runtime_get_sync(framer);185185+ if (ret < 0 && ret != -EOPNOTSUPP)186186+ goto err_pm_sync;187187+188188+ mutex_lock(&framer->mutex);189189+ if (framer->power_count == 0 && framer->ops->power_on) {190190+ ret = framer->ops->power_on(framer);191191+ if (ret < 0) {192192+ dev_err(&framer->dev, "framer poweron failed --> %d\n", ret);193193+ goto err_pwr_on;194194+ }195195+ }196196+ ++framer->power_count;197197+ mutex_unlock(&framer->mutex);198198+ return 0;199199+200200+err_pwr_on:201201+ mutex_unlock(&framer->mutex);202202+ framer_pm_runtime_put_sync(framer);203203+err_pm_sync:204204+ if (framer->pwr)205205+ regulator_disable(framer->pwr);206206+ return ret;207207+}208208+EXPORT_SYMBOL_GPL(framer_power_on);209209+210210+/**211211+ * framer_power_off - Disable the framer.212212+ * @framer: the framer returned by framer_get()213213+ *214214+ * Must be called before framer_exit().215215+ *216216+ * Return: %0 if successful, a negative error code otherwise217217+ */218218+int framer_power_off(struct framer *framer)219219+{220220+ int ret;221221+222222+ mutex_lock(&framer->mutex);223223+ if (framer->power_count == 1 && framer->ops->power_off) {224224+ ret = framer->ops->power_off(framer);225225+ if (ret < 0) {226226+ dev_err(&framer->dev, "framer poweroff failed --> %d\n", ret);227227+ mutex_unlock(&framer->mutex);228228+ return ret;229229+ }230230+ }231231+ --framer->power_count;232232+ mutex_unlock(&framer->mutex);233233+ framer_pm_runtime_put(framer);234234+235235+ if (framer->pwr)236236+ regulator_disable(framer->pwr);237237+238238+ return 0;239239+}240240+EXPORT_SYMBOL_GPL(framer_power_off);241241+242242+/**243243+ * framer_get_status() - Gets the framer status244244+ * @framer: the framer returned by framer_get()245245+ * @status: the status to retrieve246246+ *247247+ * Used to get the framer status. framer_init() must have been called248248+ * on the framer.249249+ *250250+ * Return: %0 if successful, a negative error code otherwise251251+ */252252+int framer_get_status(struct framer *framer, struct framer_status *status)253253+{254254+ int ret;255255+256256+ if (!framer->ops->get_status)257257+ return -EOPNOTSUPP;258258+259259+ /* Be sure to have known values (struct padding and future extensions) */260260+ memset(status, 0, sizeof(*status));261261+262262+ mutex_lock(&framer->mutex);263263+ ret = framer->ops->get_status(framer, status);264264+ mutex_unlock(&framer->mutex);265265+266266+ return ret;267267+}268268+EXPORT_SYMBOL_GPL(framer_get_status);269269+270270+/**271271+ * framer_set_config() - Sets the framer configuration272272+ * @framer: the framer returned by framer_get()273273+ * @config: the configuration to set274274+ *275275+ * Used to set the framer configuration. framer_init() must have been called276276+ * on the framer.277277+ *278278+ * Return: %0 if successful, a negative error code otherwise279279+ */280280+int framer_set_config(struct framer *framer, const struct framer_config *config)281281+{282282+ int ret;283283+284284+ if (!framer->ops->set_config)285285+ return -EOPNOTSUPP;286286+287287+ mutex_lock(&framer->mutex);288288+ ret = framer->ops->set_config(framer, config);289289+ mutex_unlock(&framer->mutex);290290+291291+ return ret;292292+}293293+EXPORT_SYMBOL_GPL(framer_set_config);294294+295295+/**296296+ * framer_get_config() - Gets the framer configuration297297+ * @framer: the framer returned by framer_get()298298+ * @config: the configuration to retrieve299299+ *300300+ * Used to get the framer configuration. framer_init() must have been called301301+ * on the framer.302302+ *303303+ * Return: %0 if successful, a negative error code otherwise304304+ */305305+int framer_get_config(struct framer *framer, struct framer_config *config)306306+{307307+ int ret;308308+309309+ if (!framer->ops->get_config)310310+ return -EOPNOTSUPP;311311+312312+ mutex_lock(&framer->mutex);313313+ ret = framer->ops->get_config(framer, config);314314+ mutex_unlock(&framer->mutex);315315+316316+ return ret;317317+}318318+EXPORT_SYMBOL_GPL(framer_get_config);319319+320320+static void framer_polling_work(struct work_struct *work)321321+{322322+ struct framer *framer = container_of(work, struct framer, polling_work.work);323323+ struct framer_status status;324324+ int ret;325325+326326+ ret = framer_get_status(framer, &status);327327+ if (ret) {328328+ dev_err(&framer->dev, "polling, get status failed (%d)\n", ret);329329+ goto end;330330+ }331331+ if (memcmp(&framer->prev_status, &status, sizeof(status))) {332332+ blocking_notifier_call_chain(&framer->notifier_list,333333+ FRAMER_EVENT_STATUS, NULL);334334+ memcpy(&framer->prev_status, &status, sizeof(status));335335+ }336336+337337+end:338338+ /* Re-schedule task in 1 sec */339339+ queue_delayed_work(system_power_efficient_wq, &framer->polling_work, 1 * HZ);340340+}341341+342342+/**343343+ * framer_notifier_register() - Registers a notifier344344+ * @framer: the framer returned by framer_get()345345+ * @nb: the notifier block to register346346+ *347347+ * Used to register a notifier block on framer events. framer_init() must have348348+ * been called on the framer.349349+ * The available framer events are present in enum framer_events.350350+ *351351+ * Return: %0 if successful, a negative error code otherwise352352+ */353353+int framer_notifier_register(struct framer *framer, struct notifier_block *nb)354354+{355355+ return blocking_notifier_chain_register(&framer->notifier_list, nb);356356+}357357+EXPORT_SYMBOL_GPL(framer_notifier_register);358358+359359+/**360360+ * framer_notifier_unregister() - Unregisters a notifier361361+ * @framer: the framer returned by framer_get()362362+ * @nb: the notifier block to unregister363363+ *364364+ * Used to unregister a notifier block. framer_init() must have365365+ * been called on the framer.366366+ *367367+ * Return: %0 if successful, a negative error code otherwise368368+ */369369+int framer_notifier_unregister(struct framer *framer, struct notifier_block *nb)370370+{371371+ return blocking_notifier_chain_unregister(&framer->notifier_list, nb);372372+}373373+EXPORT_SYMBOL_GPL(framer_notifier_unregister);374374+375375+static struct framer_provider *framer_provider_of_lookup(const struct device_node *node)376376+{377377+ struct framer_provider *framer_provider;378378+379379+ list_for_each_entry(framer_provider, &framer_provider_list, list) {380380+ if (device_match_of_node(framer_provider->dev, node))381381+ return framer_provider;382382+ }383383+384384+ return ERR_PTR(-EPROBE_DEFER);385385+}386386+387387+static struct framer *framer_of_get_from_provider(struct of_phandle_args *args)388388+{389389+ struct framer_provider *framer_provider;390390+ struct framer *framer;391391+392392+ mutex_lock(&framer_provider_mutex);393393+ framer_provider = framer_provider_of_lookup(args->np);394394+ if (IS_ERR(framer_provider) || !try_module_get(framer_provider->owner)) {395395+ framer = ERR_PTR(-EPROBE_DEFER);396396+ goto end;397397+ }398398+399399+ framer = framer_provider->of_xlate(framer_provider->dev, args);400400+401401+ module_put(framer_provider->owner);402402+403403+end:404404+ mutex_unlock(&framer_provider_mutex);405405+406406+ return framer;407407+}408408+409409+static struct framer *framer_of_get_byphandle(struct device_node *np, const char *propname,410410+ int index)411411+{412412+ struct of_phandle_args args;413413+ struct framer *framer;414414+ int ret;415415+416416+ ret = of_parse_phandle_with_optional_args(np, propname, "#framer-cells", index, &args);417417+ if (ret)418418+ return ERR_PTR(-ENODEV);419419+420420+ if (!of_device_is_available(args.np)) {421421+ framer = ERR_PTR(-ENODEV);422422+ goto out_node_put;423423+ }424424+425425+ framer = framer_of_get_from_provider(&args);426426+427427+out_node_put:428428+ of_node_put(args.np);429429+430430+ return framer;431431+}432432+433433+static struct framer *framer_of_get_byparent(struct device_node *np, int index)434434+{435435+ struct of_phandle_args args;436436+ struct framer *framer;437437+438438+ args.np = of_get_parent(np);439439+ args.args_count = 1;440440+ args.args[0] = index;441441+442442+ while (args.np) {443443+ framer = framer_of_get_from_provider(&args);444444+ if (IS_ERR(framer) && PTR_ERR(framer) != -EPROBE_DEFER) {445445+ args.np = of_get_next_parent(args.np);446446+ continue;447447+ }448448+ of_node_put(args.np);449449+ return framer;450450+ }451451+452452+ return ERR_PTR(-ENODEV);453453+}454454+455455+/**456456+ * framer_get() - lookup and obtain a reference to a framer.457457+ * @dev: device that requests the framer458458+ * @con_id: name of the framer from device's point of view459459+ *460460+ * Returns the framer driver, after getting a refcount to it; or461461+ * -ENODEV if there is no such framer. The caller is responsible for462462+ * calling framer_put() to release that count.463463+ */464464+struct framer *framer_get(struct device *dev, const char *con_id)465465+{466466+ struct framer *framer = ERR_PTR(-ENODEV);467467+ struct device_link *link;468468+ int ret;469469+470470+ if (dev->of_node) {471471+ if (con_id)472472+ framer = framer_of_get_byphandle(dev->of_node, con_id, 0);473473+ else474474+ framer = framer_of_get_byparent(dev->of_node, 0);475475+ }476476+477477+ if (IS_ERR(framer))478478+ return framer;479479+480480+ get_device(&framer->dev);481481+482482+ if (!try_module_get(framer->ops->owner)) {483483+ ret = -EPROBE_DEFER;484484+ goto err_put_device;485485+ }486486+487487+ link = device_link_add(dev, &framer->dev, DL_FLAG_STATELESS);488488+ if (!link) {489489+ dev_err(dev, "failed to create device_link to %s\n", dev_name(&framer->dev));490490+ ret = -EPROBE_DEFER;491491+ goto err_module_put;492492+ }493493+494494+ return framer;495495+496496+err_module_put:497497+ module_put(framer->ops->owner);498498+err_put_device:499499+ put_device(&framer->dev);500500+ return ERR_PTR(ret);501501+}502502+EXPORT_SYMBOL_GPL(framer_get);503503+504504+/**505505+ * framer_put() - release the framer506506+ * @dev: device that wants to release this framer507507+ * @framer: the framer returned by framer_get()508508+ *509509+ * Releases a refcount the caller received from framer_get().510510+ */511511+void framer_put(struct device *dev, struct framer *framer)512512+{513513+ device_link_remove(dev, &framer->dev);514514+515515+ module_put(framer->ops->owner);516516+ put_device(&framer->dev);517517+}518518+EXPORT_SYMBOL_GPL(framer_put);519519+520520+static void devm_framer_put(struct device *dev, void *res)521521+{522522+ struct framer *framer = *(struct framer **)res;523523+524524+ framer_put(dev, framer);525525+}526526+527527+/**528528+ * devm_framer_get() - lookup and obtain a reference to a framer.529529+ * @dev: device that requests this framer530530+ * @con_id: name of the framer from device's point of view531531+ *532532+ * Gets the framer using framer_get(), and associates a device with it using533533+ * devres. On driver detach, framer_put() function is invoked on the devres534534+ * data, then, devres data is freed.535535+ */536536+struct framer *devm_framer_get(struct device *dev, const char *con_id)537537+{538538+ struct framer **ptr, *framer;539539+540540+ ptr = devres_alloc(devm_framer_put, sizeof(*ptr), GFP_KERNEL);541541+ if (!ptr)542542+ return ERR_PTR(-ENOMEM);543543+544544+ framer = framer_get(dev, con_id);545545+ if (!IS_ERR(framer)) {546546+ *ptr = framer;547547+ devres_add(dev, ptr);548548+ } else {549549+ devres_free(ptr);550550+ return framer;551551+ }552552+553553+ return framer;554554+}555555+EXPORT_SYMBOL_GPL(devm_framer_get);556556+557557+/**558558+ * devm_framer_optional_get() - lookup and obtain a reference to an optional559559+ * framer.560560+ * @dev: device that requests this framer561561+ * @con_id: name of the framer from device's point of view562562+ *563563+ * Same as devm_framer_get() except that if the framer does not exist, it is not564564+ * considered an error and -ENODEV will not be returned. Instead the NULL framer565565+ * is returned.566566+ */567567+struct framer *devm_framer_optional_get(struct device *dev, const char *con_id)568568+{569569+ struct framer *framer = devm_framer_get(dev, con_id);570570+571571+ if (PTR_ERR(framer) == -ENODEV)572572+ framer = NULL;573573+574574+ return framer;575575+}576576+EXPORT_SYMBOL_GPL(devm_framer_optional_get);577577+578578+static void framer_notify_status_work(struct work_struct *work)579579+{580580+ struct framer *framer = container_of(work, struct framer, notify_status_work);581581+582582+ blocking_notifier_call_chain(&framer->notifier_list, FRAMER_EVENT_STATUS, NULL);583583+}584584+585585+void framer_notify_status_change(struct framer *framer)586586+{587587+ /* Can be called from atomic context -> just schedule a task to call588588+ * blocking notifiers589589+ */590590+ queue_work(system_power_efficient_wq, &framer->notify_status_work);591591+}592592+EXPORT_SYMBOL_GPL(framer_notify_status_change);593593+594594+/**595595+ * framer_create() - create a new framer596596+ * @dev: device that is creating the new framer597597+ * @node: device node of the framer. default to dev->of_node.598598+ * @ops: function pointers for performing framer operations599599+ *600600+ * Called to create a framer using framer framework.601601+ */602602+struct framer *framer_create(struct device *dev, struct device_node *node,603603+ const struct framer_ops *ops)604604+{605605+ struct framer *framer;606606+ int ret;607607+ int id;608608+609609+ /* get_status() is mandatory if the provider ask for polling status */610610+ if (WARN_ON((ops->flags & FRAMER_FLAG_POLL_STATUS) && !ops->get_status))611611+ return ERR_PTR(-EINVAL);612612+613613+ framer = kzalloc(sizeof(*framer), GFP_KERNEL);614614+ if (!framer)615615+ return ERR_PTR(-ENOMEM);616616+617617+ id = ida_alloc(&framer_ida, GFP_KERNEL);618618+ if (id < 0) {619619+ dev_err(dev, "unable to get id\n");620620+ ret = id;621621+ goto free_framer;622622+ }623623+624624+ device_initialize(&framer->dev);625625+ mutex_init(&framer->mutex);626626+ INIT_WORK(&framer->notify_status_work, framer_notify_status_work);627627+ INIT_DELAYED_WORK(&framer->polling_work, framer_polling_work);628628+ BLOCKING_INIT_NOTIFIER_HEAD(&framer->notifier_list);629629+630630+ framer->dev.class = framer_class;631631+ framer->dev.parent = dev;632632+ framer->dev.of_node = node ? node : dev->of_node;633633+ framer->id = id;634634+ framer->ops = ops;635635+636636+ ret = dev_set_name(&framer->dev, "framer-%s.%d", dev_name(dev), id);637637+ if (ret)638638+ goto put_dev;639639+640640+ /* framer-supply */641641+ framer->pwr = regulator_get_optional(&framer->dev, "framer");642642+ if (IS_ERR(framer->pwr)) {643643+ ret = PTR_ERR(framer->pwr);644644+ if (ret == -EPROBE_DEFER)645645+ goto put_dev;646646+647647+ framer->pwr = NULL;648648+ }649649+650650+ ret = device_add(&framer->dev);651651+ if (ret)652652+ goto put_dev;653653+654654+ if (pm_runtime_enabled(dev)) {655655+ pm_runtime_enable(&framer->dev);656656+ pm_runtime_no_callbacks(&framer->dev);657657+ }658658+659659+ return framer;660660+661661+put_dev:662662+ put_device(&framer->dev); /* calls framer_release() which frees resources */663663+ return ERR_PTR(ret);664664+665665+free_framer:666666+ kfree(framer);667667+ return ERR_PTR(ret);668668+}669669+EXPORT_SYMBOL_GPL(framer_create);670670+671671+/**672672+ * framer_destroy() - destroy the framer673673+ * @framer: the framer to be destroyed674674+ *675675+ * Called to destroy the framer.676676+ */677677+void framer_destroy(struct framer *framer)678678+{679679+ /* polling_work should already be stopped but if framer_exit() was not680680+ * called (bug), here it's the last time to do that ...681681+ */682682+ cancel_delayed_work_sync(&framer->polling_work);683683+ cancel_work_sync(&framer->notify_status_work);684684+ pm_runtime_disable(&framer->dev);685685+ device_unregister(&framer->dev); /* calls framer_release() which frees resources */686686+}687687+EXPORT_SYMBOL_GPL(framer_destroy);688688+689689+static void devm_framer_destroy(struct device *dev, void *res)690690+{691691+ struct framer *framer = *(struct framer **)res;692692+693693+ framer_destroy(framer);694694+}695695+696696+/**697697+ * devm_framer_create() - create a new framer698698+ * @dev: device that is creating the new framer699699+ * @node: device node of the framer700700+ * @ops: function pointers for performing framer operations701701+ *702702+ * Creates a new framer device adding it to the framer class.703703+ * While at that, it also associates the device with the framer using devres.704704+ * On driver detach, release function is invoked on the devres data,705705+ * then, devres data is freed.706706+ */707707+struct framer *devm_framer_create(struct device *dev, struct device_node *node,708708+ const struct framer_ops *ops)709709+{710710+ struct framer **ptr, *framer;711711+712712+ ptr = devres_alloc(devm_framer_destroy, sizeof(*ptr), GFP_KERNEL);713713+ if (!ptr)714714+ return ERR_PTR(-ENOMEM);715715+716716+ framer = framer_create(dev, node, ops);717717+ if (!IS_ERR(framer)) {718718+ *ptr = framer;719719+ devres_add(dev, ptr);720720+ } else {721721+ devres_free(ptr);722722+ }723723+724724+ return framer;725725+}726726+EXPORT_SYMBOL_GPL(devm_framer_create);727727+728728+/**729729+ * framer_provider_simple_of_xlate() - returns the framer instance from framer provider730730+ * @dev: the framer provider device731731+ * @args: of_phandle_args (not used here)732732+ *733733+ * Intended to be used by framer provider for the common case where #framer-cells is734734+ * 0. For other cases where #framer-cells is greater than '0', the framer provider735735+ * should provide a custom of_xlate function that reads the *args* and returns736736+ * the appropriate framer.737737+ */738738+struct framer *framer_provider_simple_of_xlate(struct device *dev, struct of_phandle_args *args)739739+{740740+ struct class_dev_iter iter;741741+ struct framer *framer;742742+743743+ class_dev_iter_init(&iter, framer_class, NULL, NULL);744744+ while ((dev = class_dev_iter_next(&iter))) {745745+ framer = dev_to_framer(dev);746746+ if (args->np != framer->dev.of_node)747747+ continue;748748+749749+ class_dev_iter_exit(&iter);750750+ return framer;751751+ }752752+753753+ class_dev_iter_exit(&iter);754754+ return ERR_PTR(-ENODEV);755755+}756756+EXPORT_SYMBOL_GPL(framer_provider_simple_of_xlate);757757+758758+/**759759+ * __framer_provider_of_register() - create/register framer provider with the framework760760+ * @dev: struct device of the framer provider761761+ * @owner: the module owner containing of_xlate762762+ * @of_xlate: function pointer to obtain framer instance from framer provider763763+ *764764+ * Creates struct framer_provider from dev and of_xlate function pointer.765765+ * This is used in the case of dt boot for finding the framer instance from766766+ * framer provider.767767+ */768768+struct framer_provider *769769+__framer_provider_of_register(struct device *dev, struct module *owner,770770+ struct framer *(*of_xlate)(struct device *dev,771771+ struct of_phandle_args *args))772772+{773773+ struct framer_provider *framer_provider;774774+775775+ framer_provider = kzalloc(sizeof(*framer_provider), GFP_KERNEL);776776+ if (!framer_provider)777777+ return ERR_PTR(-ENOMEM);778778+779779+ framer_provider->dev = dev;780780+ framer_provider->owner = owner;781781+ framer_provider->of_xlate = of_xlate;782782+783783+ of_node_get(framer_provider->dev->of_node);784784+785785+ mutex_lock(&framer_provider_mutex);786786+ list_add_tail(&framer_provider->list, &framer_provider_list);787787+ mutex_unlock(&framer_provider_mutex);788788+789789+ return framer_provider;790790+}791791+EXPORT_SYMBOL_GPL(__framer_provider_of_register);792792+793793+/**794794+ * framer_provider_of_unregister() - unregister framer provider from the framework795795+ * @framer_provider: framer provider returned by framer_provider_of_register()796796+ *797797+ * Removes the framer_provider created using framer_provider_of_register().798798+ */799799+void framer_provider_of_unregister(struct framer_provider *framer_provider)800800+{801801+ mutex_lock(&framer_provider_mutex);802802+ list_del(&framer_provider->list);803803+ mutex_unlock(&framer_provider_mutex);804804+805805+ of_node_put(framer_provider->dev->of_node);806806+ kfree(framer_provider);807807+}808808+EXPORT_SYMBOL_GPL(framer_provider_of_unregister);809809+810810+static void devm_framer_provider_of_unregister(struct device *dev, void *res)811811+{812812+ struct framer_provider *framer_provider = *(struct framer_provider **)res;813813+814814+ framer_provider_of_unregister(framer_provider);815815+}816816+817817+/**818818+ * __devm_framer_provider_of_register() - create/register framer provider with819819+ * the framework820820+ * @dev: struct device of the framer provider821821+ * @owner: the module owner containing of_xlate822822+ * @of_xlate: function pointer to obtain framer instance from framer provider823823+ *824824+ * Creates struct framer_provider from dev and of_xlate function pointer.825825+ * This is used in the case of dt boot for finding the framer instance from826826+ * framer provider. While at that, it also associates the device with the827827+ * framer provider using devres. On driver detach, release function is invoked828828+ * on the devres data, then, devres data is freed.829829+ */830830+struct framer_provider *831831+__devm_framer_provider_of_register(struct device *dev, struct module *owner,832832+ struct framer *(*of_xlate)(struct device *dev,833833+ struct of_phandle_args *args))834834+{835835+ struct framer_provider **ptr, *framer_provider;836836+837837+ ptr = devres_alloc(devm_framer_provider_of_unregister, sizeof(*ptr), GFP_KERNEL);838838+ if (!ptr)839839+ return ERR_PTR(-ENOMEM);840840+841841+ framer_provider = __framer_provider_of_register(dev, owner, of_xlate);842842+ if (!IS_ERR(framer_provider)) {843843+ *ptr = framer_provider;844844+ devres_add(dev, ptr);845845+ } else {846846+ devres_free(ptr);847847+ }848848+849849+ return framer_provider;850850+}851851+EXPORT_SYMBOL_GPL(__devm_framer_provider_of_register);852852+853853+/**854854+ * framer_release() - release the framer855855+ * @dev: the dev member within framer856856+ *857857+ * When the last reference to the device is removed, it is called858858+ * from the embedded kobject as release method.859859+ */860860+static void framer_release(struct device *dev)861861+{862862+ struct framer *framer;863863+864864+ framer = dev_to_framer(dev);865865+ regulator_put(framer->pwr);866866+ ida_free(&framer_ida, framer->id);867867+ kfree(framer);868868+}869869+870870+static int __init framer_core_init(void)871871+{872872+ framer_class = class_create("framer");873873+ if (IS_ERR(framer_class)) {874874+ pr_err("failed to create framer class (%pe)\n", framer_class);875875+ return PTR_ERR(framer_class);876876+ }877877+878878+ framer_class->dev_release = framer_release;879879+880880+ return 0;881881+}882882+device_initcall(framer_core_init);
+8
drivers/net/wan/framer/pef2256/Makefile
···11+# SPDX-License-Identifier: GPL-2.022+#33+# Makefile for the pef2256 driver.44+#55+66+obj-$(CONFIG_FRAMER_PEF2256) += framer-pef2256.o77+88+framer-pef2256-objs := pef2256.o
···11+// SPDX-License-Identifier: GPL-2.022+/*33+ * PEF2256 also known as FALC56 driver44+ *55+ * Copyright 2023 CS GROUP France66+ *77+ * Author: Herve Codina <herve.codina@bootlin.com>88+ */99+1010+#include <linux/framer/pef2256.h>1111+#include <linux/clk.h>1212+#include <linux/framer/framer-provider.h>1313+#include <linux/gpio/consumer.h>1414+#include <linux/interrupt.h>1515+#include <linux/io.h>1616+#include <linux/mfd/core.h>1717+#include <linux/module.h>1818+#include <linux/notifier.h>1919+#include <linux/of.h>2020+#include <linux/of_platform.h>2121+#include <linux/platform_device.h>2222+#include <linux/regmap.h>2323+#include <linux/slab.h>2424+#include "pef2256-regs.h"2525+2626+enum pef2256_frame_type {2727+ PEF2256_FRAME_E1_DOUBLEFRAME,2828+ PEF2256_FRAME_E1_CRC4_MULTIFRAME,2929+ PEF2256_FRAME_E1_AUTO_MULTIFRAME,3030+ PEF2256_FRAME_T1J1_4FRAME,3131+ PEF2256_FRAME_T1J1_12FRAME,3232+ PEF2256_FRAME_T1J1_24FRAME,3333+ PEF2256_FRAME_T1J1_72FRAME,3434+};3535+3636+struct pef2256 {3737+ struct device *dev;3838+ struct regmap *regmap;3939+ enum pef2256_version version;4040+ struct clk *mclk;4141+ struct clk *sclkr;4242+ struct clk *sclkx;4343+ struct gpio_desc *reset_gpio;4444+ unsigned long sysclk_rate;4545+ u32 data_rate;4646+ bool is_tx_falling_edge;4747+ bool is_subordinate;4848+ enum pef2256_frame_type frame_type;4949+ u8 channel_phase;5050+ atomic_t carrier;5151+ struct framer *framer;5252+};5353+5454+static u8 pef2256_read8(struct pef2256 *pef2256, int offset)5555+{5656+ int val;5757+5858+ regmap_read(pef2256->regmap, offset, &val);5959+ return val;6060+}6161+6262+static void pef2256_write8(struct pef2256 *pef2256, int offset, u8 val)6363+{6464+ regmap_write(pef2256->regmap, offset, val);6565+}6666+6767+static void pef2256_clrbits8(struct pef2256 *pef2256, int offset, u8 clr)6868+{6969+ regmap_clear_bits(pef2256->regmap, offset, clr);7070+}7171+7272+static void pef2256_setbits8(struct pef2256 *pef2256, int offset, u8 set)7373+{7474+ regmap_set_bits(pef2256->regmap, offset, set);7575+}7676+7777+static void pef2256_clrsetbits8(struct pef2256 *pef2256, int offset, u8 clr, u8 set)7878+{7979+ regmap_update_bits(pef2256->regmap, offset, clr | set, set);8080+}8181+8282+enum pef2256_version pef2256_get_version(struct pef2256 *pef2256)8383+{8484+ enum pef2256_version version = PEF2256_VERSION_UNKNOWN;8585+ u8 vstr, wid;8686+8787+ vstr = pef2256_read8(pef2256, PEF2256_VSTR);8888+ wid = pef2256_read8(pef2256, PEF2256_WID);8989+9090+ switch (vstr) {9191+ case PEF2256_VSTR_VERSION_12:9292+ if ((wid & PEF2256_12_WID_MASK) == PEF2256_12_WID_VERSION_12)9393+ version = PEF2256_VERSION_1_2;9494+ break;9595+ case PEF2256_VSTR_VERSION_2x:9696+ switch (wid & PEF2256_2X_WID_MASK) {9797+ case PEF2256_2X_WID_VERSION_21:9898+ version = PEF2256_VERSION_2_1;9999+ break;100100+ case PEF2256_2X_WID_VERSION_22:101101+ version = PEF2256_VERSION_2_2;102102+ break;103103+ }104104+ break;105105+ case PEF2256_VSTR_VERSION_21:106106+ version = PEF2256_VERSION_2_1;107107+ break;108108+ }109109+110110+ if (version == PEF2256_VERSION_UNKNOWN)111111+ dev_err(pef2256->dev, "Unknown version (0x%02x, 0x%02x)\n", vstr, wid);112112+113113+ return version;114114+}115115+EXPORT_SYMBOL_GPL(pef2256_get_version);116116+117117+enum pef2256_gcm_config_item {118118+ PEF2256_GCM_CONFIG_1544000 = 0,119119+ PEF2256_GCM_CONFIG_2048000,120120+ PEF2256_GCM_CONFIG_8192000,121121+ PEF2256_GCM_CONFIG_10000000,122122+ PEF2256_GCM_CONFIG_12352000,123123+ PEF2256_GCM_CONFIG_16384000,124124+};125125+126126+struct pef2256_gcm_config {127127+ u8 gcm_12[6];128128+ u8 gcm_2x[8];129129+};130130+131131+static const struct pef2256_gcm_config pef2256_gcm_configs[] = {132132+ [PEF2256_GCM_CONFIG_1544000] = {133133+ .gcm_12 = {0xF0, 0x51, 0x00, 0x80, 0x00, 0x15},134134+ .gcm_2x = {0x00, 0x15, 0x00, 0x08, 0x00, 0x3F, 0x9C, 0xDF},135135+ },136136+ [PEF2256_GCM_CONFIG_2048000] = {137137+ .gcm_12 = {0x00, 0x58, 0xD2, 0xC2, 0x00, 0x10},138138+ .gcm_2x = {0x00, 0x18, 0xFB, 0x0B, 0x00, 0x2F, 0xDB, 0xDF},139139+ },140140+ [PEF2256_GCM_CONFIG_8192000] = {141141+ .gcm_12 = {0x00, 0x58, 0xD2, 0xC2, 0x03, 0x10},142142+ .gcm_2x = {0x00, 0x18, 0xFB, 0x0B, 0x00, 0x0B, 0xDB, 0xDF},143143+ },144144+ [PEF2256_GCM_CONFIG_10000000] = {145145+ .gcm_12 = {0x90, 0x51, 0x81, 0x8F, 0x04, 0x10},146146+ .gcm_2x = {0x40, 0x1B, 0x3D, 0x0A, 0x00, 0x07, 0xC9, 0xDC},147147+ },148148+ [PEF2256_GCM_CONFIG_12352000] = {149149+ .gcm_12 = {0xF0, 0x51, 0x00, 0x80, 0x07, 0x15},150150+ .gcm_2x = {0x00, 0x19, 0x00, 0x08, 0x01, 0x0A, 0x98, 0xDA},151151+ },152152+ [PEF2256_GCM_CONFIG_16384000] = {153153+ .gcm_12 = {0x00, 0x58, 0xD2, 0xC2, 0x07, 0x10},154154+ .gcm_2x = {0x00, 0x18, 0xFB, 0x0B, 0x01, 0x0B, 0xDB, 0xDF},155155+ },156156+};157157+158158+static int pef2256_setup_gcm(struct pef2256 *pef2256)159159+{160160+ enum pef2256_gcm_config_item item;161161+ unsigned long mclk_rate;162162+ const u8 *gcm;163163+ int i, count;164164+165165+ mclk_rate = clk_get_rate(pef2256->mclk);166166+ switch (mclk_rate) {167167+ case 1544000:168168+ item = PEF2256_GCM_CONFIG_1544000;169169+ break;170170+ case 2048000:171171+ item = PEF2256_GCM_CONFIG_2048000;172172+ break;173173+ case 8192000:174174+ item = PEF2256_GCM_CONFIG_8192000;175175+ break;176176+ case 10000000:177177+ item = PEF2256_GCM_CONFIG_10000000;178178+ break;179179+ case 12352000:180180+ item = PEF2256_GCM_CONFIG_12352000;181181+ break;182182+ case 16384000:183183+ item = PEF2256_GCM_CONFIG_16384000;184184+ break;185185+ default:186186+ dev_err(pef2256->dev, "Unsupported v2.x MCLK rate %lu\n", mclk_rate);187187+ return -EINVAL;188188+ }189189+190190+ BUILD_BUG_ON(item >= ARRAY_SIZE(pef2256_gcm_configs));191191+192192+ if (pef2256->version == PEF2256_VERSION_1_2) {193193+ gcm = pef2256_gcm_configs[item].gcm_12;194194+ count = ARRAY_SIZE(pef2256_gcm_configs[item].gcm_12);195195+ } else {196196+ gcm = pef2256_gcm_configs[item].gcm_2x;197197+ count = ARRAY_SIZE(pef2256_gcm_configs[item].gcm_2x);198198+ }199199+200200+ for (i = 0; i < count; i++)201201+ pef2256_write8(pef2256, PEF2256_GCM(i + 1), *(gcm + i));202202+203203+ return 0;204204+}205205+206206+static int pef2256_setup_e1_line(struct pef2256 *pef2256)207207+{208208+ u8 fmr1, fmr2;209209+210210+ /* RCLK output : DPLL clock, DCO-X enabled, DCO-X internal ref clock */211211+ pef2256_write8(pef2256, PEF2256_CMR1, 0x00);212212+213213+ /* SCLKR selected, SCLKX selected,214214+ * receive synchro pulse sourced by SYPR,215215+ * transmit synchro pulse sourced by SYPX,216216+ * DCO-X center frequency enabled217217+ */218218+ pef2256_write8(pef2256, PEF2256_CMR2, PEF2256_CMR2_DCOXC);219219+220220+ if (pef2256->is_subordinate) {221221+ /* select RCLK source = 2M, disable switching from RCLK to SYNC */222222+ pef2256_clrsetbits8(pef2256, PEF2256_CMR1, PEF2256_CMR1_RS_MASK,223223+ PEF2256_CMR1_RS_DCOR_2048 | PEF2256_CMR1_DCS);224224+ }225225+226226+ /* slave mode, local loop off, mode short-haul227227+ * In v2.x, bit3 is a forced 1 bit in the datasheet -> Need to be set.228228+ */229229+ if (pef2256->version == PEF2256_VERSION_1_2)230230+ pef2256_write8(pef2256, PEF2256_LIM0, 0x00);231231+ else232232+ pef2256_write8(pef2256, PEF2256_LIM0, PEF2256_2X_LIM0_BIT3);233233+234234+ /* "master" mode */235235+ if (!pef2256->is_subordinate)236236+ pef2256_setbits8(pef2256, PEF2256_LIM0, PEF2256_LIM0_MAS);237237+238238+ /* analog interface selected, remote loop off */239239+ pef2256_write8(pef2256, PEF2256_LIM1, 0x00);240240+241241+ /* receive input threshold = 0,21V */242242+ if (pef2256->version == PEF2256_VERSION_1_2)243243+ pef2256_clrsetbits8(pef2256, PEF2256_LIM1, PEF2256_12_LIM1_RIL_MASK,244244+ PEF2256_12_LIM1_RIL_210);245245+ else246246+ pef2256_clrsetbits8(pef2256, PEF2256_LIM1, PEF2256_2X_LIM1_RIL_MASK,247247+ PEF2256_2X_LIM1_RIL_210);248248+249249+ /* transmit pulse mask, default value from datasheet250250+ * transmit line in normal operation251251+ */252252+ if (pef2256->version == PEF2256_VERSION_1_2)253253+ pef2256_write8(pef2256, PEF2256_XPM0, 0x7B);254254+ else255255+ pef2256_write8(pef2256, PEF2256_XPM0, 0x9C);256256+ pef2256_write8(pef2256, PEF2256_XPM1, 0x03);257257+ pef2256_write8(pef2256, PEF2256_XPM2, 0x00);258258+259259+ /* HDB3 coding, no alarm simulation */260260+ pef2256_write8(pef2256, PEF2256_FMR0, PEF2256_FMR0_XC_HDB3 | PEF2256_FMR0_RC_HDB3);261261+262262+ /* E1, frame format, 2 Mbit/s system data rate, no AIS263263+ * transmission to remote end or system interface, payload loop264264+ * off, transmit remote alarm on265265+ */266266+ fmr1 = 0x00;267267+ fmr2 = PEF2256_FMR2_AXRA;268268+ switch (pef2256->frame_type) {269269+ case PEF2256_FRAME_E1_DOUBLEFRAME:270270+ fmr2 |= PEF2256_FMR2_RFS_DOUBLEFRAME;271271+ break;272272+ case PEF2256_FRAME_E1_CRC4_MULTIFRAME:273273+ fmr1 |= PEF2256_FMR1_XFS;274274+ fmr2 |= PEF2256_FMR2_RFS_CRC4_MULTIFRAME;275275+ break;276276+ case PEF2256_FRAME_E1_AUTO_MULTIFRAME:277277+ fmr1 |= PEF2256_FMR1_XFS;278278+ fmr2 |= PEF2256_FMR2_RFS_AUTO_MULTIFRAME;279279+ break;280280+ default:281281+ dev_err(pef2256->dev, "Unsupported frame type %d\n", pef2256->frame_type);282282+ return -EINVAL;283283+ }284284+ pef2256_clrsetbits8(pef2256, PEF2256_FMR1, PEF2256_FMR1_XFS, fmr1);285285+ pef2256_write8(pef2256, PEF2256_FMR2, fmr2);286286+287287+ if (!pef2256->is_subordinate) {288288+ /* SEC input, active high */289289+ pef2256_write8(pef2256, PEF2256_GPC1, PEF2256_GPC1_CSFP_SEC_IN_HIGH);290290+ } else {291291+ /* FSC output, active high */292292+ pef2256_write8(pef2256, PEF2256_GPC1, PEF2256_GPC1_CSFP_FSC_OUT_HIGH);293293+ }294294+295295+ /* SCLKR, SCLKX, RCLK configured to inputs,296296+ * XFMS active low, CLK1 and CLK2 pin configuration297297+ */298298+ pef2256_write8(pef2256, PEF2256_PC5, 0x00);299299+ pef2256_write8(pef2256, PEF2256_PC6, 0x00);300300+301301+ /* port RCLK is output */302302+ pef2256_setbits8(pef2256, PEF2256_PC5, PEF2256_PC5_CRP);303303+304304+ return 0;305305+}306306+307307+static void pef2256_setup_e1_los(struct pef2256 *pef2256)308308+{309309+ /* detection of LOS alarm = 176 pulses (ie (10 + 1) * 16) */310310+ pef2256_write8(pef2256, PEF2256_PCD, 10);311311+ /* recovery of LOS alarm = 22 pulses (ie 21 + 1) */312312+ pef2256_write8(pef2256, PEF2256_PCR, 21);313313+ /* E1 default for the receive slicer threshold */314314+ pef2256_write8(pef2256, PEF2256_LIM2, PEF2256_LIM2_SLT_THR50);315315+ if (pef2256->is_subordinate) {316316+ /* Loop-timed */317317+ pef2256_setbits8(pef2256, PEF2256_LIM2, PEF2256_LIM2_ELT);318318+ }319319+}320320+321321+static int pef2256_setup_e1_system(struct pef2256 *pef2256)322322+{323323+ u8 sic1, fmr1;324324+325325+ /* 2.048 MHz system clocking rate, receive buffer 2 frames, transmit326326+ * buffer bypass, data sampled and transmitted on the falling edge of327327+ * SCLKR/X, automatic freeze signaling, data is active in the first328328+ * channel phase329329+ */330330+ pef2256_write8(pef2256, PEF2256_SIC1, 0x00);331331+ pef2256_write8(pef2256, PEF2256_SIC2, 0x00);332332+ pef2256_write8(pef2256, PEF2256_SIC3, 0x00);333333+334334+ if (pef2256->is_subordinate) {335335+ /* transmit buffer size = 2 frames, transparent mode */336336+ pef2256_clrsetbits8(pef2256, PEF2256_SIC1, PEF2256_SIC1_XBS_MASK,337337+ PEF2256_SIC1_XBS_2FRAMES);338338+ }339339+340340+ if (pef2256->version != PEF2256_VERSION_1_2) {341341+ /* during inactive channel phase switch RDO/RSIG into tri-state */342342+ pef2256_setbits8(pef2256, PEF2256_SIC3, PEF2256_SIC3_RTRI);343343+ }344344+345345+ if (pef2256->is_tx_falling_edge) {346346+ /* falling edge sync pulse transmit, rising edge sync pulse receive */347347+ pef2256_clrsetbits8(pef2256, PEF2256_SIC3, PEF2256_SIC3_RESX, PEF2256_SIC3_RESR);348348+ } else {349349+ /* rising edge sync pulse transmit, falling edge sync pulse receive */350350+ pef2256_clrsetbits8(pef2256, PEF2256_SIC3, PEF2256_SIC3_RESR, PEF2256_SIC3_RESX);351351+ }352352+353353+ /* transmit offset counter (XCO10..0) = 4 */354354+ pef2256_write8(pef2256, PEF2256_XC0, 0);355355+ pef2256_write8(pef2256, PEF2256_XC1, 4);356356+ /* receive offset counter (RCO10..0) = 4 */357357+ pef2256_write8(pef2256, PEF2256_RC0, 0);358358+ pef2256_write8(pef2256, PEF2256_RC1, 4);359359+360360+ /* system clock rate */361361+ switch (pef2256->sysclk_rate) {362362+ case 2048000:363363+ sic1 = PEF2256_SIC1_SSC_2048;364364+ break;365365+ case 4096000:366366+ sic1 = PEF2256_SIC1_SSC_4096;367367+ break;368368+ case 8192000:369369+ sic1 = PEF2256_SIC1_SSC_8192;370370+ break;371371+ case 16384000:372372+ sic1 = PEF2256_SIC1_SSC_16384;373373+ break;374374+ default:375375+ dev_err(pef2256->dev, "Unsupported sysclk rate %lu\n", pef2256->sysclk_rate);376376+ return -EINVAL;377377+ }378378+ pef2256_clrsetbits8(pef2256, PEF2256_SIC1, PEF2256_SIC1_SSC_MASK, sic1);379379+380380+ /* data clock rate */381381+ switch (pef2256->data_rate) {382382+ case 2048000:383383+ fmr1 = PEF2256_FMR1_SSD_2048;384384+ sic1 = PEF2256_SIC1_SSD_2048;385385+ break;386386+ case 4096000:387387+ fmr1 = PEF2256_FMR1_SSD_4096;388388+ sic1 = PEF2256_SIC1_SSD_4096;389389+ break;390390+ case 8192000:391391+ fmr1 = PEF2256_FMR1_SSD_8192;392392+ sic1 = PEF2256_SIC1_SSD_8192;393393+ break;394394+ case 16384000:395395+ fmr1 = PEF2256_FMR1_SSD_16384;396396+ sic1 = PEF2256_SIC1_SSD_16384;397397+ break;398398+ default:399399+ dev_err(pef2256->dev, "Unsupported data rate %u\n", pef2256->data_rate);400400+ return -EINVAL;401401+ }402402+ pef2256_clrsetbits8(pef2256, PEF2256_FMR1, PEF2256_FMR1_SSD_MASK, fmr1);403403+ pef2256_clrsetbits8(pef2256, PEF2256_SIC1, PEF2256_SIC1_SSD_MASK, sic1);404404+405405+ /* channel phase */406406+ pef2256_clrsetbits8(pef2256, PEF2256_SIC2, PEF2256_SIC2_SICS_MASK,407407+ PEF2256_SIC2_SICS(pef2256->channel_phase));408408+409409+ return 0;410410+}411411+412412+static void pef2256_setup_e1_signaling(struct pef2256 *pef2256)413413+{414414+ /* All bits of the transmitted service word are cleared */415415+ pef2256_write8(pef2256, PEF2256_XSW, PEF2256_XSW_XY(0x1F));416416+417417+ /* CAS disabled and clear spare bit values */418418+ pef2256_write8(pef2256, PEF2256_XSP, 0x00);419419+420420+ if (pef2256->is_subordinate) {421421+ /* transparent mode */422422+ pef2256_setbits8(pef2256, PEF2256_XSW, PEF2256_XSW_XTM);423423+ }424424+425425+ /* Si-Bit, Spare bit For International, FAS word */426426+ pef2256_setbits8(pef2256, PEF2256_XSW, PEF2256_XSW_XSIS);427427+ pef2256_setbits8(pef2256, PEF2256_XSP, PEF2256_XSP_XSIF);428428+429429+ /* no transparent mode active */430430+ pef2256_write8(pef2256, PEF2256_TSWM, 0x00);431431+}432432+433433+static void pef2256_setup_e1_errors(struct pef2256 *pef2256)434434+{435435+ /* error counter latched every 1s */436436+ pef2256_setbits8(pef2256, PEF2256_FMR1, PEF2256_FMR1_ECM);437437+438438+ /* error counter mode COFA */439439+ pef2256_setbits8(pef2256, PEF2256_GCR, PEF2256_GCR_ECMC);440440+441441+ /* errors in service words have no influence */442442+ pef2256_setbits8(pef2256, PEF2256_RC0, PEF2256_RC0_SWD);443443+444444+ /* 4 consecutive incorrect FAS causes loss of sync */445445+ pef2256_setbits8(pef2256, PEF2256_RC0, PEF2256_RC0_ASY4);446446+}447447+448448+static int pef2256_setup_e1(struct pef2256 *pef2256)449449+{450450+ int ret;451451+452452+ /* Setup, Master clocking mode (GCM8..1) */453453+ ret = pef2256_setup_gcm(pef2256);454454+ if (ret)455455+ return ret;456456+457457+ /* Select E1 mode */458458+ pef2256_write8(pef2256, PEF2256_FMR1, 0x00);459459+460460+ /* internal second timer, power on */461461+ pef2256_write8(pef2256, PEF2256_GCR, 0x00);462462+463463+ /* Setup line interface */464464+ ret = pef2256_setup_e1_line(pef2256);465465+ if (ret)466466+ return ret;467467+468468+ /* Setup Loss-of-signal detection and recovery */469469+ pef2256_setup_e1_los(pef2256);470470+471471+ /* Setup system interface */472472+ ret = pef2256_setup_e1_system(pef2256);473473+ if (ret)474474+ return ret;475475+476476+ /* Setup signaling */477477+ pef2256_setup_e1_signaling(pef2256);478478+479479+ /* Setup errors counters and condition */480480+ pef2256_setup_e1_errors(pef2256);481481+482482+ /* status changed interrupt at both up and down */483483+ pef2256_setbits8(pef2256, PEF2256_GCR, PEF2256_GCR_SCI);484484+485485+ /* Clear any ISR2 pending interrupts and unmask needed interrupts */486486+ pef2256_read8(pef2256, PEF2256_ISR2);487487+ pef2256_clrbits8(pef2256, PEF2256_IMR2, PEF2256_INT2_LOS | PEF2256_INT2_AIS);488488+489489+ /* reset lines */490490+ pef2256_write8(pef2256, PEF2256_CMDR, PEF2256_CMDR_RRES | PEF2256_CMDR_XRES);491491+ return 0;492492+}493493+494494+static void pef2256_isr_default_handler(struct pef2256 *pef2256, u8 nbr, u8 isr)495495+{496496+ dev_warn_ratelimited(pef2256->dev, "ISR%u: 0x%02x not handled\n", nbr, isr);497497+}498498+499499+static bool pef2256_is_carrier_on(struct pef2256 *pef2256)500500+{501501+ u8 frs0;502502+503503+ frs0 = pef2256_read8(pef2256, PEF2256_FRS0);504504+ return !(frs0 & (PEF2256_FRS0_LOS | PEF2256_FRS0_AIS));505505+}506506+507507+static void pef2256_isr2_handler(struct pef2256 *pef2256, u8 nbr, u8 isr)508508+{509509+ bool carrier;510510+511511+ if (isr & (PEF2256_INT2_LOS | PEF2256_INT2_AIS)) {512512+ carrier = pef2256_is_carrier_on(pef2256);513513+ if (atomic_xchg(&pef2256->carrier, carrier) != carrier)514514+ framer_notify_status_change(pef2256->framer);515515+ }516516+}517517+518518+static irqreturn_t pef2256_irq_handler(int irq, void *priv)519519+{520520+ static void (*pef2256_isr_handler[])(struct pef2256 *, u8, u8) = {521521+ [0] = pef2256_isr_default_handler,522522+ [1] = pef2256_isr_default_handler,523523+ [2] = pef2256_isr2_handler,524524+ [3] = pef2256_isr_default_handler,525525+ [4] = pef2256_isr_default_handler,526526+ [5] = pef2256_isr_default_handler527527+ };528528+ struct pef2256 *pef2256 = (struct pef2256 *)priv;529529+ u8 gis;530530+ u8 isr;531531+ u8 n;532532+533533+ gis = pef2256_read8(pef2256, PEF2256_GIS);534534+535535+ for (n = 0; n < ARRAY_SIZE(pef2256_isr_handler); n++) {536536+ if (gis & PEF2256_GIS_ISR(n)) {537537+ isr = pef2256_read8(pef2256, PEF2256_ISR(n));538538+ pef2256_isr_handler[n](pef2256, n, isr);539539+ }540540+ }541541+542542+ return IRQ_HANDLED;543543+}544544+545545+static int pef2256_check_rates(struct pef2256 *pef2256, unsigned long sysclk_rate,546546+ unsigned long data_rate)547547+{548548+ unsigned long rate;549549+550550+ switch (sysclk_rate) {551551+ case 2048000:552552+ case 4096000:553553+ case 8192000:554554+ case 16384000:555555+ break;556556+ default:557557+ dev_err(pef2256->dev, "Unsupported system clock rate %lu\n", sysclk_rate);558558+ return -EINVAL;559559+ }560560+561561+ for (rate = data_rate; rate <= data_rate * 4; rate *= 2) {562562+ if (rate == sysclk_rate)563563+ return 0;564564+ }565565+ dev_err(pef2256->dev, "Unsupported data rate %lu with system clock rate %lu\n",566566+ data_rate, sysclk_rate);567567+ return -EINVAL;568568+}569569+570570+static int pef2556_of_parse(struct pef2256 *pef2256, struct device_node *np)571571+{572572+ int ret;573573+574574+ pef2256->data_rate = 2048000;575575+ ret = of_property_read_u32(np, "lantiq,data-rate-bps", &pef2256->data_rate);576576+ if (ret && ret != -EINVAL) {577577+ dev_err(pef2256->dev, "%pOF: failed to read lantiq,data-rate-bps\n", np);578578+ return ret;579579+ }580580+581581+ ret = pef2256_check_rates(pef2256, pef2256->sysclk_rate, pef2256->data_rate);582582+ if (ret)583583+ return ret;584584+585585+ pef2256->is_tx_falling_edge = of_property_read_bool(np, "lantiq,clock-falling-edge");586586+587587+ pef2256->channel_phase = 0;588588+ ret = of_property_read_u8(np, "lantiq,channel-phase", &pef2256->channel_phase);589589+ if (ret && ret != -EINVAL) {590590+ dev_err(pef2256->dev, "%pOF: failed to read lantiq,channel-phase\n",591591+ np);592592+ return ret;593593+ }594594+ if (pef2256->channel_phase >= pef2256->sysclk_rate / pef2256->data_rate) {595595+ dev_err(pef2256->dev, "%pOF: Invalid lantiq,channel-phase %u\n",596596+ np, pef2256->channel_phase);597597+ return -EINVAL;598598+ }599599+600600+ return 0;601601+}602602+603603+static const struct regmap_config pef2256_regmap_config = {604604+ .reg_bits = 32,605605+ .val_bits = 8,606606+ .max_register = 0xff,607607+};608608+609609+static const struct mfd_cell pef2256_devs[] = {610610+ { .name = "lantiq-pef2256-pinctrl", },611611+};612612+613613+static int pef2256_add_audio_devices(struct pef2256 *pef2256)614614+{615615+ const char *compatible = "lantiq,pef2256-codec";616616+ struct mfd_cell *audio_devs;617617+ struct device_node *np;618618+ unsigned int count = 0;619619+ unsigned int i;620620+ int ret;621621+622622+ for_each_available_child_of_node(pef2256->dev->of_node, np) {623623+ if (of_device_is_compatible(np, compatible))624624+ count++;625625+ }626626+627627+ if (!count)628628+ return 0;629629+630630+ audio_devs = kcalloc(count, sizeof(*audio_devs), GFP_KERNEL);631631+ if (!audio_devs)632632+ return -ENOMEM;633633+634634+ for (i = 0; i < count; i++) {635635+ audio_devs[i].name = "framer-codec";636636+ audio_devs[i].of_compatible = compatible;637637+ audio_devs[i].id = i;638638+ }639639+640640+ ret = mfd_add_devices(pef2256->dev, 0, audio_devs, count, NULL, 0, NULL);641641+ kfree(audio_devs);642642+ return ret;643643+}644644+645645+static int pef2256_framer_get_status(struct framer *framer, struct framer_status *status)646646+{647647+ struct pef2256 *pef2256 = framer_get_drvdata(framer);648648+649649+ status->link_is_on = !!atomic_read(&pef2256->carrier);650650+ return 0;651651+}652652+653653+static int pef2256_framer_set_config(struct framer *framer, const struct framer_config *config)654654+{655655+ struct pef2256 *pef2256 = framer_get_drvdata(framer);656656+657657+ if (config->iface != FRAMER_IFACE_E1) {658658+ dev_err(pef2256->dev, "Only E1 line is currently supported\n");659659+ return -EOPNOTSUPP;660660+ }661661+662662+ switch (config->clock_type) {663663+ case FRAMER_CLOCK_EXT:664664+ pef2256->is_subordinate = true;665665+ break;666666+ case FRAMER_CLOCK_INT:667667+ pef2256->is_subordinate = false;668668+ break;669669+ default:670670+ return -EINVAL;671671+ }672672+673673+ /* Apply the new settings */674674+ return pef2256_setup_e1(pef2256);675675+}676676+677677+static int pef2256_framer_get_config(struct framer *framer, struct framer_config *config)678678+{679679+ struct pef2256 *pef2256 = framer_get_drvdata(framer);680680+681681+ config->iface = FRAMER_IFACE_E1;682682+ config->clock_type = pef2256->is_subordinate ? FRAMER_CLOCK_EXT : FRAMER_CLOCK_INT;683683+ config->line_clock_rate = 2048000;684684+ return 0;685685+}686686+687687+static const struct framer_ops pef2256_framer_ops = {688688+ .owner = THIS_MODULE,689689+ .get_status = pef2256_framer_get_status,690690+ .get_config = pef2256_framer_get_config,691691+ .set_config = pef2256_framer_set_config,692692+};693693+694694+static int pef2256_probe(struct platform_device *pdev)695695+{696696+ struct device_node *np = pdev->dev.of_node;697697+ unsigned long sclkr_rate, sclkx_rate;698698+ struct framer_provider *framer_provider;699699+ struct pef2256 *pef2256;700700+ const char *version_txt;701701+ void __iomem *iomem;702702+ int ret;703703+ int irq;704704+705705+ pef2256 = devm_kzalloc(&pdev->dev, sizeof(*pef2256), GFP_KERNEL);706706+ if (!pef2256)707707+ return -ENOMEM;708708+709709+ pef2256->dev = &pdev->dev;710710+ atomic_set(&pef2256->carrier, 0);711711+712712+ pef2256->is_subordinate = true;713713+ pef2256->frame_type = PEF2256_FRAME_E1_DOUBLEFRAME;714714+715715+ iomem = devm_platform_ioremap_resource(pdev, 0);716716+ if (IS_ERR(iomem))717717+ return PTR_ERR(iomem);718718+719719+ pef2256->regmap = devm_regmap_init_mmio(&pdev->dev, iomem,720720+ &pef2256_regmap_config);721721+ if (IS_ERR(pef2256->regmap)) {722722+ dev_err(&pdev->dev, "Failed to initialise Regmap (%ld)\n",723723+ PTR_ERR(pef2256->regmap));724724+ return PTR_ERR(pef2256->regmap);725725+ }726726+727727+ pef2256->mclk = devm_clk_get_enabled(&pdev->dev, "mclk");728728+ if (IS_ERR(pef2256->mclk))729729+ return PTR_ERR(pef2256->mclk);730730+731731+ pef2256->sclkr = devm_clk_get_enabled(&pdev->dev, "sclkr");732732+ if (IS_ERR(pef2256->sclkr))733733+ return PTR_ERR(pef2256->sclkr);734734+735735+ pef2256->sclkx = devm_clk_get_enabled(&pdev->dev, "sclkx");736736+ if (IS_ERR(pef2256->sclkx))737737+ return PTR_ERR(pef2256->sclkx);738738+739739+ /* Both SCLKR (receive) and SCLKX (transmit) must have the same rate,740740+ * stored as sysclk_rate.741741+ * The exact value will be checked at pef2256_check_rates()742742+ */743743+ sclkr_rate = clk_get_rate(pef2256->sclkr);744744+ sclkx_rate = clk_get_rate(pef2256->sclkx);745745+ if (sclkr_rate != sclkx_rate) {746746+ dev_err(pef2256->dev, "clk rate mismatch. sclkr %lu Hz, sclkx %lu Hz\n",747747+ sclkr_rate, sclkx_rate);748748+ return -EINVAL;749749+ }750750+ pef2256->sysclk_rate = sclkr_rate;751751+752752+ /* Reset the component. The MCLK clock must be active during reset */753753+ pef2256->reset_gpio = devm_gpiod_get_optional(&pdev->dev, "reset", GPIOD_OUT_LOW);754754+ if (IS_ERR(pef2256->reset_gpio))755755+ return PTR_ERR(pef2256->reset_gpio);756756+ if (pef2256->reset_gpio) {757757+ gpiod_set_value_cansleep(pef2256->reset_gpio, 1);758758+ usleep_range(10, 20);759759+ gpiod_set_value_cansleep(pef2256->reset_gpio, 0);760760+ usleep_range(10, 20);761761+ }762762+763763+ pef2256->version = pef2256_get_version(pef2256);764764+ switch (pef2256->version) {765765+ case PEF2256_VERSION_1_2:766766+ version_txt = "1.2";767767+ break;768768+ case PEF2256_VERSION_2_1:769769+ version_txt = "2.1";770770+ break;771771+ case PEF2256_VERSION_2_2:772772+ version_txt = "2.2";773773+ break;774774+ default:775775+ return -ENODEV;776776+ }777777+ dev_info(pef2256->dev, "Version %s detected\n", version_txt);778778+779779+ ret = pef2556_of_parse(pef2256, np);780780+ if (ret)781781+ return ret;782782+783783+ /* Create the framer. It can be used on interrupts */784784+ pef2256->framer = devm_framer_create(pef2256->dev, NULL, &pef2256_framer_ops);785785+ if (IS_ERR(pef2256->framer))786786+ return PTR_ERR(pef2256->framer);787787+788788+ framer_set_drvdata(pef2256->framer, pef2256);789789+790790+ /* Disable interrupts */791791+ pef2256_write8(pef2256, PEF2256_IMR0, 0xff);792792+ pef2256_write8(pef2256, PEF2256_IMR1, 0xff);793793+ pef2256_write8(pef2256, PEF2256_IMR2, 0xff);794794+ pef2256_write8(pef2256, PEF2256_IMR3, 0xff);795795+ pef2256_write8(pef2256, PEF2256_IMR4, 0xff);796796+ pef2256_write8(pef2256, PEF2256_IMR5, 0xff);797797+798798+ /* Clear any pending interrupts */799799+ pef2256_read8(pef2256, PEF2256_ISR0);800800+ pef2256_read8(pef2256, PEF2256_ISR1);801801+ pef2256_read8(pef2256, PEF2256_ISR2);802802+ pef2256_read8(pef2256, PEF2256_ISR3);803803+ pef2256_read8(pef2256, PEF2256_ISR4);804804+ pef2256_read8(pef2256, PEF2256_ISR5);805805+806806+ irq = platform_get_irq(pdev, 0);807807+ if (irq < 0)808808+ return irq;809809+ ret = devm_request_irq(pef2256->dev, irq, pef2256_irq_handler, 0, "pef2256", pef2256);810810+ if (ret < 0)811811+ return ret;812812+813813+ platform_set_drvdata(pdev, pef2256);814814+815815+ ret = mfd_add_devices(pef2256->dev, 0, pef2256_devs,816816+ ARRAY_SIZE(pef2256_devs), NULL, 0, NULL);817817+ if (ret) {818818+ dev_err(pef2256->dev, "add devices failed (%d)\n", ret);819819+ return ret;820820+ }821821+822822+ ret = pef2256_setup_e1(pef2256);823823+ if (ret)824824+ return ret;825825+826826+ framer_provider = devm_framer_provider_of_register(pef2256->dev,827827+ framer_provider_simple_of_xlate);828828+ if (IS_ERR(framer_provider))829829+ return PTR_ERR(framer_provider);830830+831831+ /* Add audio devices */832832+ ret = pef2256_add_audio_devices(pef2256);833833+ if (ret < 0) {834834+ dev_err(pef2256->dev, "add audio devices failed (%d)\n", ret);835835+ return ret;836836+ }837837+838838+ return 0;839839+}840840+841841+static int pef2256_remove(struct platform_device *pdev)842842+{843843+ struct pef2256 *pef2256 = platform_get_drvdata(pdev);844844+845845+ /* Disable interrupts */846846+ pef2256_write8(pef2256, PEF2256_IMR0, 0xff);847847+ pef2256_write8(pef2256, PEF2256_IMR1, 0xff);848848+ pef2256_write8(pef2256, PEF2256_IMR2, 0xff);849849+ pef2256_write8(pef2256, PEF2256_IMR3, 0xff);850850+ pef2256_write8(pef2256, PEF2256_IMR4, 0xff);851851+ pef2256_write8(pef2256, PEF2256_IMR5, 0xff);852852+853853+ return 0;854854+}855855+856856+static const struct of_device_id pef2256_id_table[] = {857857+ { .compatible = "lantiq,pef2256" },858858+ {} /* sentinel */859859+};860860+MODULE_DEVICE_TABLE(of, pef2256_id_table);861861+862862+static struct platform_driver pef2256_driver = {863863+ .driver = {864864+ .name = "lantiq-pef2256",865865+ .of_match_table = pef2256_id_table,866866+ },867867+ .probe = pef2256_probe,868868+ .remove = pef2256_remove,869869+};870870+module_platform_driver(pef2256_driver);871871+872872+struct regmap *pef2256_get_regmap(struct pef2256 *pef2256)873873+{874874+ return pef2256->regmap;875875+}876876+EXPORT_SYMBOL_GPL(pef2256_get_regmap);877877+878878+MODULE_AUTHOR("Herve Codina <herve.codina@bootlin.com>");879879+MODULE_DESCRIPTION("PEF2256 driver");880880+MODULE_LICENSE("GPL");
+15
drivers/pinctrl/Kconfig
···366366 open drain configuration for the Palmas series devices like367367 TPS65913, TPS80036 etc.368368369369+config PINCTRL_PEF2256370370+ tristate "Lantiq PEF2256 (FALC56) pin controller driver"371371+ depends on OF && FRAMER_PEF2256372372+ select PINMUX373373+ select PINCONF374374+ select GENERIC_PINCONF375375+ help376376+ This option enables the pin controller support for the Lantiq PEF2256377377+ framer, also known as FALC56.378378+379379+ If unsure, say N.380380+381381+ To compile this driver as a module, choose M here: the382382+ module will be called pinctrl-pef2256.383383+369384config PINCTRL_PIC32370385 bool "Microchip PIC32 pin controller driver"371386 depends on OF