summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorJeremy Kerr <jk@codeconstruct.com.au>2023-03-31 17:15:01 +0800
committerAlexandre Belloni <alexandre.belloni@bootlin.com>2023-04-28 08:19:01 +0200
commit5844564143575a8dbcbcece0084da059faeca5df (patch)
tree3faff951d9b82b68215279b1648479f41a5dcebc /drivers
parent21203e098cd3c1760de8112d750ceeedf09a6dad (diff)
downloadlinux-5844564143575a8dbcbcece0084da059faeca5df.tar.gz
linux-5844564143575a8dbcbcece0084da059faeca5df.tar.bz2
linux-5844564143575a8dbcbcece0084da059faeca5df.zip
i3c: ast2600: Add AST2600 platform-specific driver
Now that we have platform-specific infrastructure for the dw i3c driver, add platform support for the ASPEED AST2600 SoC. The AST2600 has a small set of "i3c global" registers, providing platform-level i3c configuration outside of the i3c core. For the ast2600, we need a couple of extra setup operations: - on probe: find the i3c global register set and parse the SDA pullup resistor values - on init: set the pullups accordingly, and set the i3c instance IDs Signed-off-by: Jeremy Kerr <jk@codeconstruct.com.au> Reviewed-by: Joel Stanley <joel@jms.id.au> Link: https://lore.kernel.org/r/20230331091501.3800299-4-jk@codeconstruct.com.au Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/i3c/master/Kconfig14
-rw-r--r--drivers/i3c/master/Makefile1
-rw-r--r--drivers/i3c/master/ast2600-i3c-master.c168
3 files changed, 183 insertions, 0 deletions
diff --git a/drivers/i3c/master/Kconfig b/drivers/i3c/master/Kconfig
index 3b8f95916f46..90dee3ec5520 100644
--- a/drivers/i3c/master/Kconfig
+++ b/drivers/i3c/master/Kconfig
@@ -22,6 +22,20 @@ config DW_I3C_MASTER
This driver can also be built as a module. If so, the module
will be called dw-i3c-master.
+config AST2600_I3C_MASTER
+ tristate "ASPEED AST2600 I3C master driver"
+ depends on DW_I3C_MASTER
+ depends on ARCH_ASPEED || COMPILE_TEST
+ select MFD_SYSCON
+ help
+ Support for ASPEED AST2600 I3C Controller.
+
+ This hardware is an instance of the DW I3C controller; this
+ driver adds platform- specific support for AST2600 hardware.
+
+ This driver can also be built as a module. If so, the module
+ will be called ast2600-i3c-master.
+
config SVC_I3C_MASTER
tristate "Silvaco I3C Dual-Role Master driver"
depends on I3C
diff --git a/drivers/i3c/master/Makefile b/drivers/i3c/master/Makefile
index b3fee0f690b2..3e97960160bc 100644
--- a/drivers/i3c/master/Makefile
+++ b/drivers/i3c/master/Makefile
@@ -1,5 +1,6 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_CDNS_I3C_MASTER) += i3c-master-cdns.o
obj-$(CONFIG_DW_I3C_MASTER) += dw-i3c-master.o
+obj-$(CONFIG_AST2600_I3C_MASTER) += ast2600-i3c-master.o
obj-$(CONFIG_SVC_I3C_MASTER) += svc-i3c-master.o
obj-$(CONFIG_MIPI_I3C_HCI) += mipi-i3c-hci/
diff --git a/drivers/i3c/master/ast2600-i3c-master.c b/drivers/i3c/master/ast2600-i3c-master.c
new file mode 100644
index 000000000000..b3f0fe1e63c3
--- /dev/null
+++ b/drivers/i3c/master/ast2600-i3c-master.c
@@ -0,0 +1,168 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2023 Code Construct
+ *
+ * Author: Jeremy Kerr <jk@codeconstruct.com.au>
+ */
+
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#include "dw-i3c-master.h"
+
+/* AST2600-specific global register set */
+#define AST2600_I3CG_REG0(idx) (((idx) * 4 * 4) + 0x10)
+#define AST2600_I3CG_REG1(idx) (((idx) * 4 * 4) + 0x14)
+
+#define AST2600_I3CG_REG0_SDA_PULLUP_EN_MASK GENMASK(29, 28)
+#define AST2600_I3CG_REG0_SDA_PULLUP_EN_2K (0x0 << 28)
+#define AST2600_I3CG_REG0_SDA_PULLUP_EN_750 (0x2 << 28)
+
+#define AST2600_I3CG_REG1_I2C_MODE BIT(0)
+#define AST2600_I3CG_REG1_TEST_MODE BIT(1)
+#define AST2600_I3CG_REG1_ACT_MODE_MASK GENMASK(3, 2)
+#define AST2600_I3CG_REG1_ACT_MODE(x) (((x) << 2) & AST2600_I3CG_REG1_ACT_MODE_MASK)
+#define AST2600_I3CG_REG1_PENDING_INT_MASK GENMASK(7, 4)
+#define AST2600_I3CG_REG1_PENDING_INT(x) (((x) << 4) & AST2600_I3CG_REG1_PENDING_INT_MASK)
+#define AST2600_I3CG_REG1_SA_MASK GENMASK(14, 8)
+#define AST2600_I3CG_REG1_SA(x) (((x) << 8) & AST2600_I3CG_REG1_SA_MASK)
+#define AST2600_I3CG_REG1_SA_EN BIT(15)
+#define AST2600_I3CG_REG1_INST_ID_MASK GENMASK(19, 16)
+#define AST2600_I3CG_REG1_INST_ID(x) (((x) << 16) & AST2600_I3CG_REG1_INST_ID_MASK)
+
+#define AST2600_DEFAULT_SDA_PULLUP_OHMS 2000
+
+struct ast2600_i3c {
+ struct dw_i3c_master dw;
+ struct regmap *global_regs;
+ unsigned int global_idx;
+ unsigned int sda_pullup;
+};
+
+static struct ast2600_i3c *to_ast2600_i3c(struct dw_i3c_master *dw)
+{
+ return container_of(dw, struct ast2600_i3c, dw);
+}
+
+static int ast2600_i3c_pullup_to_reg(unsigned int ohms, u32 *regp)
+{
+ u32 reg;
+
+ switch (ohms) {
+ case 2000:
+ reg = AST2600_I3CG_REG0_SDA_PULLUP_EN_2K;
+ break;
+ case 750:
+ reg = AST2600_I3CG_REG0_SDA_PULLUP_EN_750;
+ break;
+ case 545:
+ reg = AST2600_I3CG_REG0_SDA_PULLUP_EN_2K |
+ AST2600_I3CG_REG0_SDA_PULLUP_EN_750;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (regp)
+ *regp = reg;
+
+ return 0;
+}
+
+static int ast2600_i3c_init(struct dw_i3c_master *dw)
+{
+ struct ast2600_i3c *i3c = to_ast2600_i3c(dw);
+ u32 reg = 0;
+ int rc;
+
+ /* reg0: set SDA pullup values */
+ rc = ast2600_i3c_pullup_to_reg(i3c->sda_pullup, &reg);
+ if (rc)
+ return rc;
+
+ rc = regmap_write(i3c->global_regs,
+ AST2600_I3CG_REG0(i3c->global_idx), reg);
+ if (rc)
+ return rc;
+
+ /* reg1: set up the instance id, but leave everything else disabled,
+ * as it's all for client mode
+ */
+ reg = AST2600_I3CG_REG1_INST_ID(i3c->global_idx);
+ rc = regmap_write(i3c->global_regs,
+ AST2600_I3CG_REG1(i3c->global_idx), reg);
+
+ return rc;
+}
+
+const struct dw_i3c_platform_ops ast2600_i3c_ops = {
+ .init = ast2600_i3c_init,
+};
+
+static int ast2600_i3c_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct of_phandle_args gspec;
+ struct ast2600_i3c *i3c;
+ int rc;
+
+ i3c = devm_kzalloc(&pdev->dev, sizeof(*i3c), GFP_KERNEL);
+ if (!i3c)
+ return -ENOMEM;
+
+ rc = of_parse_phandle_with_fixed_args(np, "aspeed,global-regs", 1, 0,
+ &gspec);
+ if (rc)
+ return -ENODEV;
+
+ i3c->global_regs = syscon_node_to_regmap(gspec.np);
+ of_node_put(gspec.np);
+
+ if (IS_ERR(i3c->global_regs))
+ return PTR_ERR(i3c->global_regs);
+
+ i3c->global_idx = gspec.args[0];
+
+ rc = of_property_read_u32(np, "sda-pullup-ohms", &i3c->sda_pullup);
+ if (rc)
+ i3c->sda_pullup = AST2600_DEFAULT_SDA_PULLUP_OHMS;
+
+ rc = ast2600_i3c_pullup_to_reg(i3c->sda_pullup, NULL);
+ if (rc)
+ dev_err(&pdev->dev, "invalid sda-pullup value %d\n",
+ i3c->sda_pullup);
+
+ i3c->dw.platform_ops = &ast2600_i3c_ops;
+ return dw_i3c_common_probe(&i3c->dw, pdev);
+}
+
+static void ast2600_i3c_remove(struct platform_device *pdev)
+{
+ struct dw_i3c_master *dw_i3c = platform_get_drvdata(pdev);
+
+ dw_i3c_common_remove(dw_i3c);
+}
+
+static const struct of_device_id ast2600_i3c_master_of_match[] = {
+ { .compatible = "aspeed,ast2600-i3c", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, ast2600_i3c_master_of_match);
+
+static struct platform_driver ast2600_i3c_driver = {
+ .probe = ast2600_i3c_probe,
+ .remove_new = ast2600_i3c_remove,
+ .driver = {
+ .name = "ast2600-i3c-master",
+ .of_match_table = ast2600_i3c_master_of_match,
+ },
+};
+module_platform_driver(ast2600_i3c_driver);
+
+MODULE_AUTHOR("Jeremy Kerr <jk@codeconstruct.com.au>");
+MODULE_DESCRIPTION("ASPEED AST2600 I3C driver");
+MODULE_LICENSE("GPL");
Uj^'޷|JUilo ȯ]rKfmAIOμt_şznVωj4B9[goDe nGC~\iGp@Ȇtm;1|؝IƽvAv֜}&~b9Cgnpy;f,(pnP:-l%P9,2SU2"#ψ]v|gc|^Fv֋wsr%#u=ǣ9i@[[$+[`9ޭ2U_.KP .zrG:NAK" )=%0 I:^YQi ⩳вgt#uX%pϊ@v߲%R_/ƖӾ75@vw `\LV9vɫY<=v8>e猛{66rE^䮮KBJaL!Zi1Ő:$q֨ayA kETw= jIc!.XYzN27 ^_^YThߐRkE=+1ݣdnHfȍ.C}Ы@zy ,Fk s]IVǨe[5T}iW<=Weᚥ[/Vl|sB@0"9md*aF*P kV]NԦ$moAԵ5SOF|Tly1HN*@ l\-tsTN zδǨe]SKcA^`#g0 ` ذ2ò=冭S^25r_fX~}Y|t="h 7PhuGF9 w'<$D*a252e 1޵K`v`rp EѰh1F qOgkw} .X@P&fYmI! tD3լ(2j*T/'>gy/7<!x"""=@p= Afv@ cx ͛`aG @.GH|ڣH@s q`B"ݧ9([d61%k 1gc0J &ZAul.maOW`l,IXȝU@2<&YQ釳,w!qR!CkܪŐZ7Ό珓UTya!F(8%@ ) Ltٛ{kou ^yVBC$FAt-$,"@xu}]4K(wbP0vK s :x@s~$Џa 5+du>_w9q M.DtSklܚuyFf)c]lBܳ$FBSvئ4E~0]L-./ކՔ{ЧdO= F=vI߯tׯ{R޼ڂLnBlUW?97/]|@s>PdVwgϗ'Eԭي"">Ę$EEz@p|vi腏GvX!X7Ue< &Ъ]bͽ Ľ t/Wq&{@稱OG(߰3N-$Sܪ[#~)sRGY6vV5 k- x譸W?t%!T%$hP;6j0,ytߵXE) U^rig֌901(:xkJ ߻Wjaм\aBsyM lyNg=bp 6n# _bRT!n#i}|Fcv VO*G SSuޢ2N ߄R(Cwh ܢڗrB&y<7,O9LTMA3˜WWr ؠ63;Q*6DŽpx`5I-3O0n/8QDq I3@b]WJ!,nSn3UtT%J@ި+ +CDW]|1'?FPݪ(J_]8̀v%\ﶺٻLqS!L o=y.K7a<|ifm F(Z!|b=\j~ֽTm!;^J`(4qkt&zk{ˠ?$(B'a!DzȀmr#Ɖ&7Pڇpjx!+$i/5۫./auٓ";|IpY6]jHyv!g((7/6?.qD==;чǷrӍV p]w x\ˤߗ'O'=s8/4Q~bf::Zi% d= ];zYͱ7ůEc'xa|>G7M%Dg vV1?'ezV;hW'7yc ,؄)ōw͌h6AG!VZ.5c{IdJ>BL%@u8 Vf@|s_g:Sv B`Ci; j2FG*xqvg6oTE~#fX 8tPFEcv]YPuû} jDagjY:O%bg08T1oWk@!;"\öXo2$i1(SGX=g7YaꬓH16k1J}JԝI|?q{4Y oΰ VF._79&0Nۈbkh]4+4Öpf:cq)rs41<] s: c5bl"JccO;(7 PU?s5;7ϻ2gIs\V+ ė._D"VAsvJDhsv. hLg]f4b\lm-9:vꑼ$%2۲GxCߟAi!/ݹ*óRY?<DCǠ93PZbQ2+@%e[G֬[K^Ab {_F_thSc]I!KA4+vUHb_P[&ճbcu}eٗmgݽv7K\fҨG%+**T#dh*nHms1Ge⹝93ilUiFwC-Dkkktڧ%^ypƲ ю`ObdV < ǽXv}@wss9)9(B;=9ޓe=;'u<.'˜a]<6ozYFwr9"o`ۼف)*1$ |@R>4XkU,fū}]xf ^b\97oDILW?ɻ!`{* W!|܃nxͽA-qfo6Xa~J-,J ߩa?1GCsvsMN{}^6|/ɇ0<ϱ|{,vϙacú::CO>i_e?7>~E(a`*9\ A@Sxɶ9k+ޛ,5[(b<"PJ} ̧':bU^ ?lFX z=gJa{`iu~v2 Z-Qk{ݥl!SKWiscVD`=>@%RblpMW K薋H4F5)KigYix$:RX-5+@]-e@#! ,Am(FLѕ=ХxU fa jsrP_n`9׮ n {tU gQSELFAUi`e`r={'; eݵ֤ F̐4fWAtM¯ _vs bAψoXd-BP$ˆe)DULJfyhs7I_[ELQn,?YGaZ)}ƈexߕ),UTơdIt)?s{򲇧ۿ~^,<:ֹ.Dh>αVpbE{%ee0^Xdw}a?e[++cKsk.ը_l >,σU1 Bx'0dG6(Mk"4mMpXq%{Z7F&H"G~ԇݤE=H!|N  jXFP^ m8TJ沉Ho|0G?/SV+HOMx]vg-WDrSZe\|0ocTTpj#'?]B76|1dXN\Nyk}:j{ Wq˲4$l9-"LG4to 4u?DBZfy4&EbI460?d;g:*Yӷ TRӳߘ?77P 1}vݨĵ9UKgt"ձ2t#HŨF6"՜2*꼸UYgcnJaĊ`+S웊s߭v^̌4AcX7~U"W1!2Bǒ]~zWLfUaïd}u+*86CbG~u^k1A5oO6o8],ֈa4GI4Z0,`CL˚oOK. ˽y fq47nOYG]1+z4_SΝߎv'JPR#gXhdhC_7d=ꕧa1j_o;hۗgrF_t xȦ |V6 tRR.0ćjYzvxgoA|y88!` hXMPg-V6E* 7NP֙;|{z!Wz͎VQ5{ɑJ=VAC2-m8sY Q#5vtjbDO`@wv%k+`uej)m:ڥV1d-O #otXEMQȤh EUWsP,+]k*XJ҃@7SĿ?##B˃30P o@sx[orr(20*tʹn ahh+XZK`I4 ;u=ٜh rIgVDKc$vEh+A٭\cA)h>R'=sqcg;gͳe深/+ȹ"׻v|e'L-E"Cy3/Guy$Ϧv r7JTh*XY,a _-z(0e~!fi_eLHGɻ!f@80˃8E)I'{oZzV6H1Lf*N3O Ml/ ?2lCqIu^]/<f> (;)BgA̽o]O6pOhÖ\ܬ47[1XWs>]Z3A5PW<-Ut}Q'&~y/Qq;Xb\Tb=~mИ57 |zxQeWlBˆ=Hsf n}'=u<ƣv7&}1";U0uIIJi3z8 0-yj. eQ Sq&(ߣo7Sɣ ۶!aU`@'h$ee[_",ku ,UʐO v6p ;_Lkhv~2ݺR[x*Ң{3 uxP dN0#, Z璅 >C(TFW&GAah-Mʉyb Ur%pt4;3w3N$mxnya;;ˆۚorru.ӒE& ID'׶bc@;x?K_~07.`n ^z-•ʊ@qc}V>>գKFpIl*J쎗ӻXrD~Dlǩ 3 ٭u,ή_{Y:UCv590OPn u` 7p=# DFG+oڱVelj*I"hVt}xζs`px.H: IvdSw2ΌS?<ņ'#l NI1o ڻ_h.7K>&/} C#u srѷnP lSv.ehqԶQu]{H%*[!A.9\9-XJ.Z~VMFͷe61cΪײl猭 4!r Xlz4(C LϿe+LKBk f nzvhϭ6DČ*I,H}YlC~0545TY9gKr1|'%>s E "nl]]5; ]S0^&TIpbSݨeỏ:\1C7$UoBg mǛgTƳ+^A`=0Y:Fy^DLŸ[!:gT,kP}N:'C\‡N[js@ר C93qrzR1&0xuۦ">} e\築kNP}S[ǒJ3+IC]8'm: npBv8݋g\wM ןW[>ڝ1zt .{9]כq@/W-Pl",++wƬu3nBxtqɘaj$p)OS7i`*<;JW>XIlszlC7=2DŽ}窖S-F"dvc2hcaSCJ/Ņ|>qm(*H-%v۾*:6+_@1F/g_ㄐZ-r0 Q+Xm`fpPV 'SLC@Z2^wvtBzul7B%T R s y9t\4 !1J׮yͿYO O:fq:E z ZӢk?)ߧ6۬{@_ uTs\:CexZq?[&Mgt}λbe؝mZ(iC-8fps O:򙐣.noX @JI`xNJ 2_k !v}! ZΣ"42[=8٥{₸55@20RY].u (;ψl}OhYF )2s9:&3vI_zw>U*|NfQ|wqЬt.H>xp|NsI\RX9Xlo0ӡƳ5OՓI;CwZ/@OrY*8 iXAZcR{EyX\*{|iˁ"3ކ4OHѳ߻: Rv~ur b\΂\$8ĶC5m̶7X=!?>zHWө6,{ $&bh.~cx Vm9Dйtx3/fnJxRQL,|,m쥕w/]NB]9TT9<UHMzҵCmZPeQv ?XavDx?}^@ y 0C'!꼀kȆwpMH,5vs`:MkmRmZ!jv\8޽B'A2S/B!D?MLXx㹓S~}uTT(" C[A~pK@sF+lbX TEewJmv[ zCo¬chtoL =GF#ോ#Z[@FӾް(F0-#|fl`p6^ aABDD@_c!96k%G? ldPBڗxSMTŮ:$:I18z|Jm*UJ$=Ma)=ccR1ЫcnI FP#l%N3wMRgzog8!W?VON޵F R[s8"=> =KjNY*˸3܎fϴ+h" 怇CZ`~,s%Y${0TNR y8JE8<ڠ!#-~ NE,uG` .ՁXZlbF/@kMY@A$|Kna7is1ba4|H#kAT ^+u{&GBɠ@TzY dMG)L?ÿw([02;-]l ϡ@" ;p <(eW:¢Fs2EaVYy=v"߻Gɐ)o$k{C5 $d5u:ZBN2}e#>MNaq|]*?,}Dݾ?rF XW,"%G(J.._Ƣ**̈́d=јD+~"_lv"S9iT=ڤXؒ,f4kndmzEU环㵐 O1md& lҌ.p M|£p&y%%(Dml|[&-y& L2$G8c7lf463X@e^8Z?VjJ  4ɫuF#ZHbp$~o2l(T"@ d`ȕ3hAZA嵆uil;3{ e5Yp J4oK~syoe7t)]o?Bۃ\0HǪ/V[uNȽ0.?VcL1Peb )2;83;ƮL' 'tT yBhW(q5Iƾ UŁQ> `Ff,9nDyxn >?39*9oe%QN7ݞ,|~->)xjp8QA}G mDLTUU%֬]w 4rs.KWU;ǼAMژw ߩ+B}ueu9'%`,m-o^Wz߭G*?44:'{Hch9uXvkvQ~t_+Txz&TCt \!-6R+LF>TI!x9%7i5Y 0Z+h"-ZKou*9NN)Coe^,1wDн>dD+5ō̽q3APK#9zp 'ȍ -ttG.^,}6{1GЌO=935K&n Ru/o0D:E:-NpfʺC@PHAeQ{₣6 ͏ӈQAG*:*挅L#&B5y _ˋ+_.42$4#3ێw5`aT.ʡ+?/X&lK0T|}pcdc5g0?`AFO(u ?]<0fFe֫PR&0>a%!^]`)]hj!"(8t3`)RN .hvG6A2JvOGl`GMm,HqVaٻ xNIDX&t&%t"m-<ׅۜ(7WY׹Zu, dR^`,^i=.LoK2U:wv80Ӆ2cV߯v~Z&դzfM/&*M8 ']gCk ) ,Vv AC*tqbE㰳U49SӋY}̛CM1>E;9mp;[۫喰SE|K;.= A41n\ á4f0"б\bˋ)`8+2Ow율ӘC}.EA|^a,w+m#{/ub>o<(z, JqPi=ަ%ˍX( *ź-gn{hfU战/L&!Ll4)@pr0~XL5tߝ<:mˡ9.sx(D4]aQfA㢫"-Z.+``򾲸'$kA'*GZ*}ZHM61M.A|\8k0`yH,ܽ.vRmW SB@tb"ZC9aZqN&ۥXKr"u^ҫ_Ci%K+7lc78X՗scgTFT0# /A#KNwX͚2bJc?>W+>UziO /Чg)s{S,nQ"=ց4U8q F$TETIa%Dq^$UEma-nbJkjU &_^cF\y7['Ia)EFfd\wsGk:JVYG:qvW,EBVUiHZjK8*sTL5*&D%cdg?7f(]g8}@YusAFXXrvǨ,݅_ɔ.JVWs\4v]6L94DqG" (@RWK6'zl\ `s혟S x2 +qݨ=DOZ2y4dܜ{we\PPEyȖ$&*FjILM(=t(Ø3qsN̝D,pEnN%fmu9݋9 ^P nήxbgii5֛tm":b(]}H|PIB) S8ngث0#`cHsᣛ9Lbe,V"ru:Trq9]0 w=(E *bkȅ`Pl ¯}0| 4F!nu bMD[Z<pkv%_qʵ[[Ը'ǧjq-sT6Qn7DJcp`F5uʊkh;ATwsxR\5NR維&1`lQ?mJOK]Q͊?d碒!/Q̚?GڐDgsj ,[ 1t>žP տ{xQ2.`&ӳKvF13v!la x+D~DWkFzwd8t*)La] AJ|Dz߫ X!F+H*nK!OD"DF''Y퀁Lb0r|XRle Hե_Yv[8δQz:oyWbxJd`Nx§`/8|cDUѭ+Zbi{p7Rh$m@8}7\Sqp^HrMm:WR!r~= G3 cQPLR|3"ؼp.}]ߚY l #z[VهsNw|S{uReml# f8M aBYb2)BC&.7n fX`9͸~ uXh,#9s2a~RF pn@-`C`O ^ZZAJs ӑ\F9e N‘eNLu-qr"]Eh[#j;Q0 sΟ]ޮ{*rM]Be7.`gObM`ONUy]̓2rH WC|;劎x܅[)S~^Qꘃ/,b=gpa¾͵nGw3Na^bf}^;1_nŞ#k#H鑙pH ȡl9UpK1 ~Vix@ UR.*qY^L̏ᢪ0nG 2`%Hjs`>GE$N!Dfzks WU*%90}j38gIuOV7EEs{彷l>Fp~ĵg|nEgtw90'=%5 O.&cCiݫTNL;/Nig`=ɲ9h_>vGUd%H8@{"򨓮C:vDBr3"K";A>&f=Nj_g>+,3@ߗ`z=^IJ}z(v^x(1,nlA EYWj~D?*~l\D*ܴ`5=7?j"OQ!$ՈNo ^rۿvk,qosn~b,@btyWb ٭ ]Wu~h_ӻ-* Ѓ(@K=C5EiT-}@+MZ fՂ&ow 1em}bC')e =T/@u5n>c( }#8+ wW=Qߴ,?f\P~8=,ºO8264_AC߆Wx|9yyFY_u>DST@&"|JKׁ^yQMaqiJ\}sAS2g?Nb<~"WکDm{nǥ-Zt(zbM5<)79ScC/pyζռDM:=/Sv\iCQB79 F$1",~-HxujD88m^ursd7ɉ4jJa{tՠh~[c|8%͠9)/^n~veh Gc#=1NԓWATI#a TeHWjJ&wٝroH(u4 m_(/Um{魣[|jimTT> benyiWUNKiB1(ZrV$M e&J[&t4Gz $!};N/;: @>xAۘr &m%=f$lX) GeTqDZLp j]XC#$@cpkLOE/j @$- H卲X|юw,+瘾>TwHy|9=/Жl:L@[PukWM?w> ". %5@C@.H'2 iI:WB {0+5*L\v8Wj$J"iC}voTtкWCs8E!5`(15=ku\Ařg0164Mq=֦uJzuیKXag*i@KZdߗasXkdۮXzf70[L lQ p#Ps olHWcoTrY`X449kA8:u$j)#K+RWL?|!0*l4dSup9ˮtb(dw.Ej)BK,)p'FgAx7\0\4J%Ȁc"o[6yOZ%HQX)t&9ީudVa\=O:grR+-Gʆ5\LTh_c0}Bpqp*RTӮ.>?hnEt# TCxЦh R5!pbj_QPpLu+9K@D9se n\ F7TK@WC1T8jfmz.opKwAϡBFz5cTC1aAR.5)HwfE5K[ UFp;npd:_Ϊ{xA"DHE*'rBGEIAJ8Q~g:>`|x_) 1{eR!%nRd b~ s2z?#s~uI;)m k%J$˔xn(KC"]t=~kN1!u3#}fŽF_k*aIa\smj%6> Y&fWJ '=Ɩ C?6;W=D;@zHi^q7KH1)9u|^ͫ]#-ɝܔ5 09F/3J4D؜Yvzlϲ3hNDNL@FPd*K( #՞" \+Kz1iuoAh}j8614U)A&4-K+[r4,6AuFn Bpm&3;6,  >6mx{Œb&Sʪ9bUX0O!qAݨuHK01 Ǖ毂MaW S)mumBLpK 9W ;dtP9:8|䭿%ijV;b- 2 \FU.YݼA(kO#;hFGx:quwwPrb;#Y2q퓶}v6~C2`oL7Cqd׮ns~=K^*nv 9$1EU'v,3S;ɘ'g;V/Ntu=*$ ,54y%|/^ܚ/89\m1Ƚ b3=6G},~*FQ,苡*6$5f;EPA\7g.p},x (M^ QOF)!K02!J)F|=,rrL׍N]L!:LJB8 +vm!7ij)iF?*7ԶEʡa7r:{(Cs{O>MUmָwÌUK%%O1*էX*c7j4;}.uC:FB\xNGz8XṾ?Ʒ A_yYp9;vUH(a J 6&TB~zŸ{)΋;;-\7sxNd>HVq9Ql䕼w{SBquK=g3rV7Uf'Lpx2o;Z"~ګT6rq1Q3M}-suo<>"S#xœ,KCLI3{AAN7U Kڳ_|VuUJn#qus8nv6Dk3x5)GQd%7CƁ}ТJ0Y[-`'=n yyy*'e1$1X&=(.J|+|QM0.qR90YS8 srv cݹRlnucJAR,w4=ڗU`C:IJ Dg )G2D"vFq}˯ɅUI+ݬA\zwXWm5<O9ZGH8+PcWNJfA!x9wQ[-%_򶶗Oq ^KսDLq|Ωƕ#8a%th"DƄ<5;5%z0u-u;'2ʼ^$y1;uE'ވ5NOӱg1{1E/sf14x}d9i( ]+ď0#Ce{ouBKfX-,ي:^ bQcċND naxA{x']!'XZ N̨Y{}( }=xul|Ux5d5T(b5Q0× Ulh[eB"[ qSɖIH?L\>/ LM83\ziF:5=wʊK'iSzhfJΩ\oziRcAi=wtof j^`;#Dgq6TYFwilmK"ۍG1s"YOX] 'Hɥ0afcØ0 1 xw]]XIB|f΄nXvݚd,3Ӹ%1V5xJ'zj:\b0v\Ji ,ۇ@p[6g 琉3:Sc3&-[gwb'sPw'sڰ]G7͑1$!/W"+Qef O|ruWq}pwkߡդJTFTh@󿦦U6A |, *f0䙞=*j!D31ꓲ>+:XǬ,},V0j>$6|VdqnS~ D{)WgKعypTN>uEf [qx*c_¬4/6/Œ*k׮ 4rn6!D'G0M&5_ %9E pK?>Z=㳪 L–, #cF쉵dA6kjgBm,0 , 6\^odpδ8k)Kr#K,\A ̴A5R!Cu~JqơeWo #γ(& Ȼk kz|-A_Ne'!1>*3N&7١~w3CxrjEԆ`362*,"av˴?\>"ooycq,pϔ|^<-o֌g3s"T)?DӺOIA! L"0^5QyՊUH^)3FܼTAĂd}v^6.SߛU<ΔC?TC9f:+.-K> M/vRߤv9$i*##kP}5+a{O8//+lj272'*\m7d^J =W}>.ۋ|c5ś0AC8/~=*\ېyEYD#?/ʫ\.[Csfd#y4l& +jTc7ںnOuƉTEaSNniut!FJ"`f uDD:!1;vΎڸ0P:tDBT.wr$_ZpvPm:w&ozoB ifDԅ~ <_ _uQ3qOӡ) !7=;A$'>Amɖ zYLXV0p%QIb eAs#Co.g]p덡}t kSdHqDa=s5c^%7\1. ~Ȥ)aHsPELE<5b-j>Je ؤ^@|DHLܵ hJZFB(! {D5h6R :mF]❕DGN0k툆oGa=!:k뷐ďaՠvN RV|۲T^-`Ti??ju3r{zeA48DHaw>($wk~ ҽGeUx;A9E?vw ˶V5& @šuWy17ĵ 3a'l\es5);l~H(I(E?U_7o AaD?A@$JRk 0O$t4'%9 98bi s"0a{?|K[ρ5(ͨ= I| LD1jmbF@.Dx~G2[,hq`NS+6?S8xqꊧ?tW' x,С{~Y_Tb\,*̳z=P$ʗ|]]:E1C_9g+^-eIn?iaegys1[$#J{/O1n)ej>G~MG33 }IПNbܧuް)!/.;KcR=EL=)M?ŢpuY=Fr%n7.6 }h;WSdC2kJ!AiryK*)>rws~N(OhBQNZG˴ɏ懻q=܃ ; )Ֆb~̴50 C`6_P$rrrZ0¿O?Or~:*A_ѧBG:A*dcjr18'9q9|ⷔ= ʅUCTVřzW$C8_iTx[3}0GoÃF@R$GS&gUpݶL`o7vP6J")Z@h`"c>B)X/H)"h)JIA?ÅJ0TC2b2_abO[d̔D.a TǟqTt_j̞kJwOlagwl&V*/,s;ov`?/OgXڲz6r8}TMx~w?Ycdѯ~?bAU+;>,7wz8m[&ө鄻 u4*`FL2'I?8r\fOtH$PC3$`)**o֛͆S`3cb&&_̻aOHgOroWLY4-㲿m}7s-@ 7l\<5z-n^=Qj;]͵ڮ4vg}y8T]{DK_6xfvd^o ۔E z%Ϳ@`p/=\??07Ah:7doo$lϏ{e|3K)C_\pkϭѽ<*t{5õkucG+|-d渜[|`azkqplst{alNao5إbB;uOf\Wh_;Wn|ٹӮO>S;p'5Rs`b?n 0*`p((]A{kΓLFpP]#螻tY8tS`|W=?ٞ9?{'\EbS1`H?'S\Q>~?P(J ]J*O <@Nӥ6Nχ?]ݟ>vjP 40@`(Vg(lq# QR4czס»pQ +̗&^?D@Q+3=3B*%+"!AŶ=`axt˺'f, lpT$xJT P oпF6%A::%#R!Hz33{ %:H'%]S3NKl%mM>'vteob22>I70`3c,Eg=3v/cWo/:n^=~,׏p߅zǯ R:ffyu;fA"_tfe/>]/cץZLjc{n-H|}WZ7kUwvoEړɧ޾{6}g/d;ܣ *#3=Śnw؈8-{?SHwfߖU-#>@QXtXaIt8|l|_V^>5g㴠J :$<}D:ܐ .|=zXv}0ђMrŖC_Q),]Q=UpYYS@*"=#-q~9:)TӶt.ڇ(yDz@AKldz4 H%1$pkq?.=7 ;@.FZJҗ1YAixp[I}|ޟTBXI[͆@MQsSƍ%ՃJ^ @)NCnd.w@.6jZ-pqxWBw1V*%m#@G+4՟h!أգJǃz_ݿnNTae!WQys3{}#3RiӾ+Ծw_[!\PY]']MO O\pkZ$Y|,2X5zgl[ls;|m1"f\zu<;d\^k?su0/}qUw!fYEA1)-Bv/]26ulɟ~3|^K(D1#gNt9R巓c,€T`5c@38~G0$QzoYRSsу!dQX^^m1lfRROSi(2LY4>tɃ? b'k$V$3DS[YE=gy'g>Dl 9{@SV%?v_t?mVp_ r=  n3Q3 W~z:ͳVwRuCj40` EխsDrS {,HssfN 2|q t?>p N?TSBr$s/^>8_WCrO]w$6/o v=E2w~* ;ub>U%;zs}.ոg$x2+;ag_糳/< .H5\}&jw,E-ׯ" 0uJ%) D@H@3ҳy,mpsD>isW av1 `j72h&ON(wa_=S]bi +~<\Q74~:Cl  ۶kj=<`?~Vy  ͵p2J0B @ILA]f  >4v@pIoGg^Gv<̱x @EҚD`ቷaD\w\{TF&*L6=NϏ-- M8g&4 03-Lؒ~18m%k/wp kGpf/6q0Lir $)_IT,?n=3u`@0|XYaSd 9Ri$tcW͕s^ѯ@vt!k}ygwW[6Rg36 0I@^3 juD/!}e_KGmV<( )Tl (jQ!̓`E5`mR#.J9S+BtE[?h@ e-nĄN^@!!E N ZY=[YgFAMtn .:`+"TN+fjsk]g ,?oi`l&Lt9XQ>}ұp~64@ҴW~X|,Zv~СDN=8KTu-Q{_ <Kyl`=UZՊ>^],0PЎ?nt'bIYh`BLl2^n\oEfE z0KksQG[~G;﷠zFVDT>ߞr'G!xwpP^z^SRQcL@/+%to|s *QC?Y T@PĒ@A$m1mx? gR mdA'N"W~ޏ}B#\7ƍ 7  F޶ ebk0Ry|.f8cPBTb7\H UmU3\8`V1!9сlK!%KY^ 9{E](0i&v1ZKѢusЇd'vE O(,W)@H dd̥ш[$TP@V$G%z}{5(Hu G*|'iM^O !oVkeo,@boKxYܵ>\6PH=p@2ޚ~޼0{d:\87#.xvgHVnxَnhGWvXeAx2~绞]fM%\=h~OL-jw!uSe0%IuoW2@R .Ծ'l4Yk=S'me/W:u`?_.uٓ/]L;u}{7ow{r.+Y\8[dDb$(lp'Le&FhvK]CnnsK) 浮C] b7\7B9A%&ٺgL.2NU|qʶ؃@J=#I6&&3\mYD(Z5:<-7+VZmL,Ae# N֍@(]9d:ND5!p;kiC$9OT bϢƔPƧE?))d5Ð@KB҃YXS:UATI;wc SMDPTjbÍ}|^c3PS PGj:Ŀ{EME 2Ur=ꗨVUJ.05lVb.7…pf5=#˷fD]zK=a$ gf#H Ѩ?aJ[f8|c?F62F,Ҭ+מ_`AۛI*E-%שgm36x;:XV6`vjʬ~܁!2=6Yu" jNK:/6jNMz R{;dzo=a{F QEQㆭ6^c~IJWѻI;N(.&TD+ uLcC)k)BݡPh{[e ۞OB_KWv0'4z/ 5򹩹ȁ(\L4:#9m+,E!ga]/hhͮز \eٽ L+M7x@{VJW?~VsӫS?In(}=0sȐfxȾgLJ[uHS>x(ĝI_I1 ZL]9N9J0X)Э#+6ݖ׭2 QJ Tbp=N[ 8m2Q5 T D$Ť'kڷLﳎ%]qvVNTceD k{@NFF87Ə"ѨcǥhB]89݂ufsKgtX, 3W=-PzF@"(2" MHlHaZzTmW ă,4@A˷v "wKǶ z%+j Mxp궽  b/ơwη0R-079:vHgICV:bn"H Wod:-ҊRU˟KU}6uRǯ%>>q^3ѻ{p6i{wW,-ҍϴ)HD*{8v1BMfF)Uzą ADLG½Fr\O9Cp.ڗ oP;G' @*듭S={ht8QDAy骋Ҿ* Offmt4 l>NWTb!/> AO>1lXbj>aS`_Йh|( ֠CT=a Q;=hS wx^_!NBz.\^c,ex-O_X|tF];y}h?*I~f:UyD=cR#l}w(遾6n ͶΕ))hnaP*=VdH~_³!+-5F} ~2Ӹ,{v`?͟w1KPCBQTc)S[ul|Qγh|= o?`<4eY~k&}sٚnB sljj}.9@*M áKYȴ79e/jV?( Imz[F@^N@Ii PEmZ#!Z<2}ׁsI^ ] a <$w07suOfo$fV}~o.z@MށJzCmƟYb"XP2?UFE^s] .:j$5E-Fvm#WB%l,ϋW{Y%{7l?"4> m X=d*DU:[f|gᯮu8@9 լ\ME42#⢈Z8  A*G,lʠiΎMu:WVU*̱lݞȠ~0:VD [Wb 5!Ȟ4K C &i XDmg|@&.Pa:[NGy&n=26du_:OJD@b>uy C,; ^hp>WN*I:uoϧC=<=0a. @ TĞU*n!^|Pf&d8|=d+a쾲}a c%&3 _n=kt| 5?zvz=Jq wQtQխwjggg(Rvm 6>i15lO4G$&! +qv u-_YYG -.':Qj:JҲ 6ѓ'h~L`ЕӜu"ݕp;_UAաC2;yO G9cn$RkMi!5zYVP[^J AWrZf@R%.* :U1#[e5H`8WA?IUYQaL=D 6H.JGW(;lHd>fL9.sCiyY\;.zs6A*qCqjbMpҌfʆ3 D:?2?+(ȉ9~@[+# y?NcMFȇ\[˜r3Q^T V-jnv,W2dm:[+g} 7}Z3Y:`' 02.av:eIi%X9fETD[e>o~_~|'2KCz{m"ivNS'?\oοk3}žo\uhUϓ3icI8MQ3³sp-;Mgg2VQ^im 7c/B-nuJ}M}n{ůQrFȎ׻RQUSMɿ;?__?Yi~=8 QB_+э5 ԀjCeN79vCz{ |r)}09<=/ǫpv*0<!Xso.߯Y˯nqou\ޢzwgLͮvtQ\&ФPs%Es礣*P5mus@WA8 U%մQ.`o񘕨KVO^EࠄVx@0X[ ^Wl ȗ ºN LCÑc2aN]>b@GozjxǥF;TđSWiYvonRZJj=GT?gsMYwd 6 2Zi]:g}~!ID*BV+lWE,jC9>ON "bN$@jUۻ𗙱43M ip#yle }oV)(F̦vrLx6Z^f*p]Q9T (׾ph"^䝟OǐmPo /wMC1+ Q l] Q0 NJ9LZX?C]b̤I=U% 2ѡW;H9P[T`bعi1{4]! @ ^ke9RI~Xs+s1)P>vpA7Q19pBS4,dI)G ,"r񨙓-q٦{ûcYY[z2AL$*̮" M_qNSvr'\n!"]s ȿ̡cn:^ u3o 2lgi ;H=lGsͪ0sՙf;0tD0[?p6s7K]oL\&v5xvty6&KDH `\ w^y8 а݊92::SYd6~wmۃM@$D'8Fad`bgtG  },1bRdH*ؔAHU 1Q9Y؈œSԉb+O/o'jߪ?2?;r jF儘Ypg]gs$BDʪZGS!=wh{5{!hb'3M3u"4ڊE(%q>X ,5HVΏ[eIGWQMg75D/6Njݢi8Z.I (-/ܕT/!ۥc]r0˱mDZlX1a@HwElA(@4ec,,pA(G$[fB6:!hmSojZ YvPXX! +bpɭ Yɐ& fpbXB ̅.q F T!8c.8;$B8ދ Xc/fXm{n(- /3P~yID a)E+o u@FU,<"TТ!DLa&@@e dbD\\@-~uqﯜI|WhU‘"@P$uH3 B鈹$dB1|yޯ*'0 e|1=b][ؽG:Eח/¦%S ݽ.!C(7.9JwjS0b X0c[[\⚻M<€fq(r+Ũ\*Q/U(^@v