brintos

brintos / linux-shallow public Read only

0
0
Text · 20.2 KiB · 71aa500 Raw
721 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (C) 2013--2024 Intel Corporation4 */5 6#include <linux/bits.h>7#include <linux/container_of.h>8#include <linux/device.h>9#include <linux/iopoll.h>10#include <linux/list.h>11#include <linux/refcount.h>12#include <linux/time64.h>13 14#include <media/v4l2-async.h>15 16#include "ipu6.h"17#include "ipu6-bus.h"18#include "ipu6-isys.h"19#include "ipu6-isys-csi2.h"20#include "ipu6-platform-isys-csi2-reg.h"21 22#define CSI_REG_HUB_GPREG_PHY_CTL(id) (CSI_REG_BASE + 0x18008 + (id) * 0x8)23#define CSI_REG_HUB_GPREG_PHY_CTL_RESET			BIT(4)24#define CSI_REG_HUB_GPREG_PHY_CTL_PWR_EN		BIT(0)25#define CSI_REG_HUB_GPREG_PHY_STATUS(id) (CSI_REG_BASE + 0x1800c + (id) * 0x8)26#define CSI_REG_HUB_GPREG_PHY_POWER_ACK			BIT(0)27#define CSI_REG_HUB_GPREG_PHY_READY			BIT(4)28 29#define MCD_PHY_POWER_STATUS_TIMEOUT			(200 * USEC_PER_MSEC)30 31/*32 * bridge to phy in buttress reg map, each phy has 16 kbytes33 * only 2 phys for TGL U and Y34 */35#define IPU6_ISYS_MCD_PHY_BASE(i)			(0x10000 + (i) * 0x4000)36 37/*38 *  There are 2 MCD DPHY instances on TGL and 1 MCD DPHY instance on ADL.39 *  Each MCD PHY has 12-lanes which has 8 data lanes and 4 clock lanes.40 *  CSI port 1, 3 (5, 7) can support max 2 data lanes.41 *  CSI port 0, 2 (4, 6) can support max 4 data lanes.42 *  PHY configurations are PPI based instead of port.43 *  Left:44 *  +---------+---------+---------+---------+--------+---------+----------+45 *  |         |         |         |         |        |         |          |46 *  | PPI     | PPI5    | PPI4    | PPI3    | PPI2   | PPI1    | PPI0     |47 *  +---------+---------+---------+---------+--------+---------+----------+48 *  |         |         |         |         |        |         |          |49 *  | x4      | unused  | D3      | D2      | C0     | D0      | D1       |50 *  |---------+---------+---------+---------+--------+---------+----------+51 *  |         |         |         |         |        |         |          |52 *  | x2x2    | C1      | D0      | D1      | C0     | D0      | D1       |53 *  ----------+---------+---------+---------+--------+---------+----------+54 *  |         |         |         |         |        |         |          |55 *  | x2x1    | C1      | D0      | unused  | C0     | D0      | D1       |56 *  +---------+---------+---------+---------+--------+---------+----------+57 *  |         |         |         |         |        |         |          |58 *  | x1x1    | C1      | D0      | unused  | C0     | D0      | unused   |59 *  +---------+---------+---------+---------+--------+---------+----------+60 *  |         |         |         |         |        |         |          |61 *  | x1x2    | C1      | D0      | D1      | C0     | D0      | unused   |62 *  +---------+---------+---------+---------+--------+---------+----------+63 *64 *  Right:65 *  +---------+---------+---------+---------+--------+---------+----------+66 *  |         |         |         |         |        |         |          |67 *  | PPI     | PPI6    | PPI7    | PPI8    | PPI9   | PPI10   | PPI11    |68 *  +---------+---------+---------+---------+--------+---------+----------+69 *  |         |         |         |         |        |         |          |70 *  | x4      | D1      | D0      | C2      | D2     | D3      | unused   |71 *  |---------+---------+---------+---------+--------+---------+----------+72 *  |         |         |         |         |        |         |          |73 *  | x2x2    | D1      | D0      | C2      | D1     | D0      | C3       |74 *  ----------+---------+---------+---------+--------+---------+----------+75 *  |         |         |         |         |        |         |          |76 *  | x2x1    | D1      | D0      | C2      | unused | D0      | C3       |77 *  +---------+---------+---------+---------+--------+---------+----------+78 *  |         |         |         |         |        |         |          |79 *  | x1x1    | unused  | D0      | C2      | unused | D0      | C3       |80 *  +---------+---------+---------+---------+--------+---------+----------+81 *  |         |         |         |         |        |         |          |82 *  | x1x2    | unused  | D0      | C2      | D1     | D0      | C3       |83 *  +---------+---------+---------+---------+--------+---------+----------+84 *85 * ppi mapping per phy :86 *87 * x4 + x4:88 * Left : port0 - PPI range {0, 1, 2, 3, 4}89 * Right: port2 - PPI range {6, 7, 8, 9, 10}90 *91 * x4 + x2x2:92 * Left: port0 - PPI range {0, 1, 2, 3, 4}93 * Right: port2 - PPI range {6, 7, 8}, port3 - PPI range {9, 10, 11}94 *95 * x2x2 + x4:96 * Left: port0 - PPI range {0, 1, 2}, port1 - PPI range {3, 4, 5}97 * Right: port2 - PPI range {6, 7, 8, 9, 10}98 *99 * x2x2 + x2x2:100 * Left : port0 - PPI range {0, 1, 2}, port1 - PPI range {3, 4, 5}101 * Right: port2 - PPI range {6, 7, 8}, port3 - PPI range {9, 10, 11}102 */103 104struct phy_reg {105	u32 reg;106	u32 val;107};108 109static const struct phy_reg common_init_regs[] = {110	/* for TGL-U, use 0x80000000 */111	{0x00000040, 0x80000000},112	{0x00000044, 0x00a80880},113	{0x00000044, 0x00b80880},114	{0x00000010, 0x0000078c},115	{0x00000344, 0x2f4401e2},116	{0x00000544, 0x924401e2},117	{0x00000744, 0x594401e2},118	{0x00000944, 0x624401e2},119	{0x00000b44, 0xfc4401e2},120	{0x00000d44, 0xc54401e2},121	{0x00000f44, 0x034401e2},122	{0x00001144, 0x8f4401e2},123	{0x00001344, 0x754401e2},124	{0x00001544, 0xe94401e2},125	{0x00001744, 0xcb4401e2},126	{0x00001944, 0xfa4401e2}127};128 129static const struct phy_reg x1_port0_config_regs[] = {130	{0x00000694, 0xc80060fa},131	{0x00000680, 0x3d4f78ea},132	{0x00000690, 0x10a0140b},133	{0x000006a8, 0xdf04010a},134	{0x00000700, 0x57050060},135	{0x00000710, 0x0030001c},136	{0x00000738, 0x5f004444},137	{0x0000073c, 0x78464204},138	{0x00000748, 0x7821f940},139	{0x0000074c, 0xb2000433},140	{0x00000494, 0xfe6030fa},141	{0x00000480, 0x29ef5ed0},142	{0x00000490, 0x10a0540b},143	{0x000004a8, 0x7a01010a},144	{0x00000500, 0xef053460},145	{0x00000510, 0xe030101c},146	{0x00000538, 0xdf808444},147	{0x0000053c, 0xc8422204},148	{0x00000540, 0x0180088c},149	{0x00000574, 0x00000000},150	{0x00000000, 0x00000000}151};152 153static const struct phy_reg x1_port1_config_regs[] = {154	{0x00000c94, 0xc80060fa},155	{0x00000c80, 0xcf47abea},156	{0x00000c90, 0x10a0840b},157	{0x00000ca8, 0xdf04010a},158	{0x00000d00, 0x57050060},159	{0x00000d10, 0x0030001c},160	{0x00000d38, 0x5f004444},161	{0x00000d3c, 0x78464204},162	{0x00000d48, 0x7821f940},163	{0x00000d4c, 0xb2000433},164	{0x00000a94, 0xc91030fa},165	{0x00000a80, 0x5a166ed0},166	{0x00000a90, 0x10a0540b},167	{0x00000aa8, 0x5d060100},168	{0x00000b00, 0xef053460},169	{0x00000b10, 0xa030101c},170	{0x00000b38, 0xdf808444},171	{0x00000b3c, 0xc8422204},172	{0x00000b40, 0x0180088c},173	{0x00000b74, 0x00000000},174	{0x00000000, 0x00000000}175};176 177static const struct phy_reg x1_port2_config_regs[] = {178	{0x00001294, 0x28f000fa},179	{0x00001280, 0x08130cea},180	{0x00001290, 0x10a0140b},181	{0x000012a8, 0xd704010a},182	{0x00001300, 0x8d050060},183	{0x00001310, 0x0030001c},184	{0x00001338, 0xdf008444},185	{0x0000133c, 0x78422204},186	{0x00001348, 0x7821f940},187	{0x0000134c, 0x5a000433},188	{0x00001094, 0x2d20b0fa},189	{0x00001080, 0xade75dd0},190	{0x00001090, 0x10a0540b},191	{0x000010a8, 0xb101010a},192	{0x00001100, 0x33053460},193	{0x00001110, 0x0030101c},194	{0x00001138, 0xdf808444},195	{0x0000113c, 0xc8422204},196	{0x00001140, 0x8180088c},197	{0x00001174, 0x00000000},198	{0x00000000, 0x00000000}199};200 201static const struct phy_reg x1_port3_config_regs[] = {202	{0x00001894, 0xc80060fa},203	{0x00001880, 0x0f90fd6a},204	{0x00001890, 0x10a0840b},205	{0x000018a8, 0xdf04010a},206	{0x00001900, 0x57050060},207	{0x00001910, 0x0030001c},208	{0x00001938, 0x5f004444},209	{0x0000193c, 0x78464204},210	{0x00001948, 0x7821f940},211	{0x0000194c, 0xb2000433},212	{0x00001694, 0x3050d0fa},213	{0x00001680, 0x0ef6d050},214	{0x00001690, 0x10a0540b},215	{0x000016a8, 0xe301010a},216	{0x00001700, 0x69053460},217	{0x00001710, 0xa030101c},218	{0x00001738, 0xdf808444},219	{0x0000173c, 0xc8422204},220	{0x00001740, 0x0180088c},221	{0x00001774, 0x00000000},222	{0x00000000, 0x00000000}223};224 225static const struct phy_reg x2_port0_config_regs[] = {226	{0x00000694, 0xc80060fa},227	{0x00000680, 0x3d4f78ea},228	{0x00000690, 0x10a0140b},229	{0x000006a8, 0xdf04010a},230	{0x00000700, 0x57050060},231	{0x00000710, 0x0030001c},232	{0x00000738, 0x5f004444},233	{0x0000073c, 0x78464204},234	{0x00000748, 0x7821f940},235	{0x0000074c, 0xb2000433},236	{0x00000494, 0xc80060fa},237	{0x00000480, 0x29ef5ed8},238	{0x00000490, 0x10a0540b},239	{0x000004a8, 0x7a01010a},240	{0x00000500, 0xef053460},241	{0x00000510, 0xe030101c},242	{0x00000538, 0xdf808444},243	{0x0000053c, 0xc8422204},244	{0x00000540, 0x0180088c},245	{0x00000574, 0x00000000},246	{0x00000294, 0xc80060fa},247	{0x00000280, 0xcb45b950},248	{0x00000290, 0x10a0540b},249	{0x000002a8, 0x8c01010a},250	{0x00000300, 0xef053460},251	{0x00000310, 0x8030101c},252	{0x00000338, 0x41808444},253	{0x0000033c, 0x32422204},254	{0x00000340, 0x0180088c},255	{0x00000374, 0x00000000},256	{0x00000000, 0x00000000}257};258 259static const struct phy_reg x2_port1_config_regs[] = {260	{0x00000c94, 0xc80060fa},261	{0x00000c80, 0xcf47abea},262	{0x00000c90, 0x10a0840b},263	{0x00000ca8, 0xdf04010a},264	{0x00000d00, 0x57050060},265	{0x00000d10, 0x0030001c},266	{0x00000d38, 0x5f004444},267	{0x00000d3c, 0x78464204},268	{0x00000d48, 0x7821f940},269	{0x00000d4c, 0xb2000433},270	{0x00000a94, 0xc80060fa},271	{0x00000a80, 0x5a166ed8},272	{0x00000a90, 0x10a0540b},273	{0x00000aa8, 0x7a01010a},274	{0x00000b00, 0xef053460},275	{0x00000b10, 0xa030101c},276	{0x00000b38, 0xdf808444},277	{0x00000b3c, 0xc8422204},278	{0x00000b40, 0x0180088c},279	{0x00000b74, 0x00000000},280	{0x00000894, 0xc80060fa},281	{0x00000880, 0x4d4f21d0},282	{0x00000890, 0x10a0540b},283	{0x000008a8, 0x5601010a},284	{0x00000900, 0xef053460},285	{0x00000910, 0x8030101c},286	{0x00000938, 0xdf808444},287	{0x0000093c, 0xc8422204},288	{0x00000940, 0x0180088c},289	{0x00000974, 0x00000000},290	{0x00000000, 0x00000000}291};292 293static const struct phy_reg x2_port2_config_regs[] = {294	{0x00001294, 0xc80060fa},295	{0x00001280, 0x08130cea},296	{0x00001290, 0x10a0140b},297	{0x000012a8, 0xd704010a},298	{0x00001300, 0x8d050060},299	{0x00001310, 0x0030001c},300	{0x00001338, 0xdf008444},301	{0x0000133c, 0x78422204},302	{0x00001348, 0x7821f940},303	{0x0000134c, 0x5a000433},304	{0x00001094, 0xc80060fa},305	{0x00001080, 0xade75dd8},306	{0x00001090, 0x10a0540b},307	{0x000010a8, 0xb101010a},308	{0x00001100, 0x33053460},309	{0x00001110, 0x0030101c},310	{0x00001138, 0xdf808444},311	{0x0000113c, 0xc8422204},312	{0x00001140, 0x8180088c},313	{0x00001174, 0x00000000},314	{0x00000e94, 0xc80060fa},315	{0x00000e80, 0x0fbf16d0},316	{0x00000e90, 0x10a0540b},317	{0x00000ea8, 0x7a01010a},318	{0x00000f00, 0xf5053460},319	{0x00000f10, 0xc030101c},320	{0x00000f38, 0xdf808444},321	{0x00000f3c, 0xc8422204},322	{0x00000f40, 0x8180088c},323	{0x00000000, 0x00000000}324};325 326static const struct phy_reg x2_port3_config_regs[] = {327	{0x00001894, 0xc80060fa},328	{0x00001880, 0x0f90fd6a},329	{0x00001890, 0x10a0840b},330	{0x000018a8, 0xdf04010a},331	{0x00001900, 0x57050060},332	{0x00001910, 0x0030001c},333	{0x00001938, 0x5f004444},334	{0x0000193c, 0x78464204},335	{0x00001948, 0x7821f940},336	{0x0000194c, 0xb2000433},337	{0x00001694, 0xc80060fa},338	{0x00001680, 0x0ef6d058},339	{0x00001690, 0x10a0540b},340	{0x000016a8, 0x7a01010a},341	{0x00001700, 0x69053460},342	{0x00001710, 0xa030101c},343	{0x00001738, 0xdf808444},344	{0x0000173c, 0xc8422204},345	{0x00001740, 0x0180088c},346	{0x00001774, 0x00000000},347	{0x00001494, 0xc80060fa},348	{0x00001480, 0xf9d34bd0},349	{0x00001490, 0x10a0540b},350	{0x000014a8, 0x7a01010a},351	{0x00001500, 0x1b053460},352	{0x00001510, 0x0030101c},353	{0x00001538, 0xdf808444},354	{0x0000153c, 0xc8422204},355	{0x00001540, 0x8180088c},356	{0x00001574, 0x00000000},357	{0x00000000, 0x00000000}358};359 360static const struct phy_reg x4_port0_config_regs[] = {361	{0x00000694, 0xc80060fa},362	{0x00000680, 0x3d4f78fa},363	{0x00000690, 0x10a0140b},364	{0x000006a8, 0xdf04010a},365	{0x00000700, 0x57050060},366	{0x00000710, 0x0030001c},367	{0x00000738, 0x5f004444},368	{0x0000073c, 0x78464204},369	{0x00000748, 0x7821f940},370	{0x0000074c, 0xb2000433},371	{0x00000494, 0xfe6030fa},372	{0x00000480, 0x29ef5ed8},373	{0x00000490, 0x10a0540b},374	{0x000004a8, 0x7a01010a},375	{0x00000500, 0xef053460},376	{0x00000510, 0xe030101c},377	{0x00000538, 0xdf808444},378	{0x0000053c, 0xc8422204},379	{0x00000540, 0x0180088c},380	{0x00000574, 0x00000004},381	{0x00000294, 0x23e030fa},382	{0x00000280, 0xcb45b950},383	{0x00000290, 0x10a0540b},384	{0x000002a8, 0x8c01010a},385	{0x00000300, 0xef053460},386	{0x00000310, 0x8030101c},387	{0x00000338, 0x41808444},388	{0x0000033c, 0x32422204},389	{0x00000340, 0x0180088c},390	{0x00000374, 0x00000004},391	{0x00000894, 0x5620b0fa},392	{0x00000880, 0x4d4f21dc},393	{0x00000890, 0x10a0540b},394	{0x000008a8, 0x5601010a},395	{0x00000900, 0xef053460},396	{0x00000910, 0x8030101c},397	{0x00000938, 0xdf808444},398	{0x0000093c, 0xc8422204},399	{0x00000940, 0x0180088c},400	{0x00000974, 0x00000004},401	{0x00000a94, 0xc91030fa},402	{0x00000a80, 0x5a166ecc},403	{0x00000a90, 0x10a0540b},404	{0x00000aa8, 0x5d01010a},405	{0x00000b00, 0xef053460},406	{0x00000b10, 0xa030101c},407	{0x00000b38, 0xdf808444},408	{0x00000b3c, 0xc8422204},409	{0x00000b40, 0x0180088c},410	{0x00000b74, 0x00000004},411	{0x00000000, 0x00000000}412};413 414static const struct phy_reg x4_port1_config_regs[] = {415	{0x00000000, 0x00000000}416};417 418static const struct phy_reg x4_port2_config_regs[] = {419	{0x00001294, 0x28f000fa},420	{0x00001280, 0x08130cfa},421	{0x00001290, 0x10c0140b},422	{0x000012a8, 0xd704010a},423	{0x00001300, 0x8d050060},424	{0x00001310, 0x0030001c},425	{0x00001338, 0xdf008444},426	{0x0000133c, 0x78422204},427	{0x00001348, 0x7821f940},428	{0x0000134c, 0x5a000433},429	{0x00001094, 0x2d20b0fa},430	{0x00001080, 0xade75dd8},431	{0x00001090, 0x10a0540b},432	{0x000010a8, 0xb101010a},433	{0x00001100, 0x33053460},434	{0x00001110, 0x0030101c},435	{0x00001138, 0xdf808444},436	{0x0000113c, 0xc8422204},437	{0x00001140, 0x8180088c},438	{0x00001174, 0x00000004},439	{0x00000e94, 0xd308d0fa},440	{0x00000e80, 0x0fbf16d0},441	{0x00000e90, 0x10a0540b},442	{0x00000ea8, 0x2c01010a},443	{0x00000f00, 0xf5053460},444	{0x00000f10, 0xc030101c},445	{0x00000f38, 0xdf808444},446	{0x00000f3c, 0xc8422204},447	{0x00000f40, 0x8180088c},448	{0x00000f74, 0x00000004},449	{0x00001494, 0x136850fa},450	{0x00001480, 0xf9d34bdc},451	{0x00001490, 0x10a0540b},452	{0x000014a8, 0x5a01010a},453	{0x00001500, 0x1b053460},454	{0x00001510, 0x0030101c},455	{0x00001538, 0xdf808444},456	{0x0000153c, 0xc8422204},457	{0x00001540, 0x8180088c},458	{0x00001574, 0x00000004},459	{0x00001694, 0x3050d0fa},460	{0x00001680, 0x0ef6d04c},461	{0x00001690, 0x10a0540b},462	{0x000016a8, 0xe301010a},463	{0x00001700, 0x69053460},464	{0x00001710, 0xa030101c},465	{0x00001738, 0xdf808444},466	{0x0000173c, 0xc8422204},467	{0x00001740, 0x0180088c},468	{0x00001774, 0x00000004},469	{0x00000000, 0x00000000}470};471 472static const struct phy_reg x4_port3_config_regs[] = {473	{0x00000000, 0x00000000}474};475 476static const struct phy_reg *x1_config_regs[4] = {477	x1_port0_config_regs,478	x1_port1_config_regs,479	x1_port2_config_regs,480	x1_port3_config_regs481};482 483static const struct phy_reg *x2_config_regs[4] = {484	x2_port0_config_regs,485	x2_port1_config_regs,486	x2_port2_config_regs,487	x2_port3_config_regs488};489 490static const struct phy_reg *x4_config_regs[4] = {491	x4_port0_config_regs,492	x4_port1_config_regs,493	x4_port2_config_regs,494	x4_port3_config_regs495};496 497static const struct phy_reg **config_regs[3] = {498	x1_config_regs,499	x2_config_regs,500	x4_config_regs501};502 503static int ipu6_isys_mcd_phy_powerup_ack(struct ipu6_isys *isys, u8 id)504{505	struct device *dev = &isys->adev->auxdev.dev;506	void __iomem *isys_base = isys->pdata->base;507	u32 val;508	int ret;509 510	val = readl(isys_base + CSI_REG_HUB_GPREG_PHY_CTL(id));511	val |= CSI_REG_HUB_GPREG_PHY_CTL_PWR_EN;512	writel(val, isys_base + CSI_REG_HUB_GPREG_PHY_CTL(id));513 514	ret = readl_poll_timeout(isys_base + CSI_REG_HUB_GPREG_PHY_STATUS(id),515				 val, val & CSI_REG_HUB_GPREG_PHY_POWER_ACK,516				 200, MCD_PHY_POWER_STATUS_TIMEOUT);517	if (ret)518		dev_err(dev, "PHY%d powerup ack timeout", id);519 520	return ret;521}522 523static int ipu6_isys_mcd_phy_powerdown_ack(struct ipu6_isys *isys, u8 id)524{525	struct device *dev = &isys->adev->auxdev.dev;526	void __iomem *isys_base = isys->pdata->base;527	u32 val;528	int ret;529 530	writel(0, isys_base + CSI_REG_HUB_GPREG_PHY_CTL(id));531	ret = readl_poll_timeout(isys_base + CSI_REG_HUB_GPREG_PHY_STATUS(id),532				 val, !(val & CSI_REG_HUB_GPREG_PHY_POWER_ACK),533				 200, MCD_PHY_POWER_STATUS_TIMEOUT);534	if (ret)535		dev_err(dev, "PHY%d powerdown ack timeout", id);536 537	return ret;538}539 540static void ipu6_isys_mcd_phy_reset(struct ipu6_isys *isys, u8 id, bool assert)541{542	void __iomem *isys_base = isys->pdata->base;543	u32 val;544 545	val = readl(isys_base + CSI_REG_HUB_GPREG_PHY_CTL(id));546	if (assert)547		val |= CSI_REG_HUB_GPREG_PHY_CTL_RESET;548	else549		val &= ~(CSI_REG_HUB_GPREG_PHY_CTL_RESET);550 551	writel(val, isys_base + CSI_REG_HUB_GPREG_PHY_CTL(id));552}553 554static int ipu6_isys_mcd_phy_ready(struct ipu6_isys *isys, u8 id)555{556	struct device *dev = &isys->adev->auxdev.dev;557	void __iomem *isys_base = isys->pdata->base;558	u32 val;559	int ret;560 561	ret = readl_poll_timeout(isys_base + CSI_REG_HUB_GPREG_PHY_STATUS(id),562				 val, val & CSI_REG_HUB_GPREG_PHY_READY,563				 200, MCD_PHY_POWER_STATUS_TIMEOUT);564	if (ret)565		dev_err(dev, "PHY%d ready ack timeout", id);566 567	return ret;568}569 570static void ipu6_isys_mcd_phy_common_init(struct ipu6_isys *isys)571{572	struct ipu6_bus_device *adev = isys->adev;573	struct ipu6_device *isp = adev->isp;574	void __iomem *isp_base = isp->base;575	struct sensor_async_sd *s_asd;576	struct v4l2_async_connection *asc;577	void __iomem *phy_base;578	unsigned int i;579	u8 phy_id;580 581	list_for_each_entry(asc, &isys->notifier.done_list, asc_entry) {582		s_asd = container_of(asc, struct sensor_async_sd, asc);583		phy_id = s_asd->csi2.port / 4;584		phy_base = isp_base + IPU6_ISYS_MCD_PHY_BASE(phy_id);585 586		for (i = 0; i < ARRAY_SIZE(common_init_regs); i++)587			writel(common_init_regs[i].val,588			       phy_base + common_init_regs[i].reg);589	}590}591 592static int ipu6_isys_driver_port_to_phy_port(struct ipu6_isys_csi2_config *cfg)593{594	int phy_port;595	int ret;596 597	if (!(cfg->nlanes == 4 || cfg->nlanes == 2 || cfg->nlanes == 1))598		return -EINVAL;599 600	/* B,F -> C0 A,E -> C1 C,G -> C2 D,H -> C4 */601	/* normalize driver port number */602	phy_port = cfg->port % 4;603 604	/* swap port number only for A and B */605	if (phy_port == 0)606		phy_port = 1;607	else if (phy_port == 1)608		phy_port = 0;609 610	ret = phy_port;611 612	/* check validity per lane configuration */613	if (cfg->nlanes == 4 && !(phy_port == 0 || phy_port == 2))614		ret = -EINVAL;615	else if ((cfg->nlanes == 2 || cfg->nlanes == 1) &&616		 !(phy_port >= 0 && phy_port <= 3))617		ret = -EINVAL;618 619	return ret;620}621 622static int ipu6_isys_mcd_phy_config(struct ipu6_isys *isys)623{624	struct device *dev = &isys->adev->auxdev.dev;625	struct ipu6_bus_device *adev = isys->adev;626	const struct phy_reg **phy_config_regs;627	struct ipu6_device *isp = adev->isp;628	void __iomem *isp_base = isp->base;629	struct sensor_async_sd *s_asd;630	struct ipu6_isys_csi2_config cfg;631	struct v4l2_async_connection *asc;632	int phy_port, phy_id;633	unsigned int i;634	void __iomem *phy_base;635 636	list_for_each_entry(asc, &isys->notifier.done_list, asc_entry) {637		s_asd = container_of(asc, struct sensor_async_sd, asc);638		cfg.port = s_asd->csi2.port;639		cfg.nlanes = s_asd->csi2.nlanes;640		phy_port = ipu6_isys_driver_port_to_phy_port(&cfg);641		if (phy_port < 0) {642			dev_err(dev, "invalid port %d for lane %d", cfg.port,643				cfg.nlanes);644			return -ENXIO;645		}646 647		phy_id = cfg.port / 4;648		phy_base = isp_base + IPU6_ISYS_MCD_PHY_BASE(phy_id);649		dev_dbg(dev, "port%d PHY%u lanes %u\n", cfg.port, phy_id,650			cfg.nlanes);651 652		phy_config_regs = config_regs[cfg.nlanes / 2];653		cfg.port = phy_port;654		for (i = 0; phy_config_regs[cfg.port][i].reg; i++)655			writel(phy_config_regs[cfg.port][i].val,656			       phy_base + phy_config_regs[cfg.port][i].reg);657	}658 659	return 0;660}661 662#define CSI_MCD_PHY_NUM		2663static refcount_t phy_power_ref_count[CSI_MCD_PHY_NUM];664 665int ipu6_isys_mcd_phy_set_power(struct ipu6_isys *isys,666				struct ipu6_isys_csi2_config *cfg,667				const struct ipu6_isys_csi2_timing *timing,668				bool on)669{670	struct device *dev = &isys->adev->auxdev.dev;671	void __iomem *isys_base = isys->pdata->base;672	u8 port, phy_id;673	refcount_t *ref;674	int ret;675 676	port = cfg->port;677	phy_id = port / 4;678 679	ref = &phy_power_ref_count[phy_id];680 681	dev_dbg(dev, "for phy %d port %d, lanes: %d\n", phy_id, port,682		cfg->nlanes);683 684	if (!isys_base || port >= isys->pdata->ipdata->csi2.nports) {685		dev_warn(dev, "invalid port ID %d\n", port);686		return -EINVAL;687	}688 689	if (on) {690		if (refcount_read(ref)) {691			dev_dbg(dev, "for phy %d is already UP", phy_id);692			refcount_inc(ref);693			return 0;694		}695 696		ret = ipu6_isys_mcd_phy_powerup_ack(isys, phy_id);697		if (ret)698			return ret;699 700		ipu6_isys_mcd_phy_reset(isys, phy_id, 0);701		ipu6_isys_mcd_phy_common_init(isys);702 703		ret = ipu6_isys_mcd_phy_config(isys);704		if (ret)705			return ret;706 707		ipu6_isys_mcd_phy_reset(isys, phy_id, 1);708		ret = ipu6_isys_mcd_phy_ready(isys, phy_id);709		if (ret)710			return ret;711 712		refcount_set(ref, 1);713		return 0;714	}715 716	if (!refcount_dec_and_test(ref))717		return 0;718 719	return ipu6_isys_mcd_phy_powerdown_ack(isys, phy_id);720}721